/*++
  This file contains 'Framework Code' and is licensed as such
  under the terms of your license agreement with Intel or your
  vendor.  This file may not be modified, except as allowed by
  additional terms of your license agreement.
--*/
/*++
Copyright (c) 1996 - 2016, Intel Corporation.

This source code and any documentation accompanying it ("Material") is furnished
under license and may only be used or copied in accordance with the terms of that
license.  No license, express or implied, by estoppel or otherwise, to any
intellectual property rights is granted to you by disclosure or delivery of these
Materials.  The Materials are subject to change without notice and should not be
construed as a commitment by Intel Corporation to market, license, sell or support
any product or technology.  Unless otherwise provided for in the license under which
this Material is provided, the Material is provided AS IS, with no warranties of
any kind, express or implied, including without limitation the implied warranties
of fitness, merchantability, or non-infringement.  Except as expressly permitted by
the license for the Material, neither Intel Corporation nor its suppliers assumes
any responsibility for any errors or inaccuracies that may appear herein.  Except
as expressly permitted by the license for the Material, no part of the Material
may be reproduced, stored in a retrieval system, transmitted in any form, or
distributed by any means without the express written consent of Intel Corporation.


Module Name:

  AcpiPlatformHooks.c
  
Abstract:

  ACPI Platform Driver Hooks

--*/

//
// Statements that include other files
//
#include "AcpiPlatform.h"
#include "AcpiPlatformHooks.h"
#include "AcpiPlatformHooksLib.h"
#include "MemWeight.h"
#include <Setup.h> // AptioV server override: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.
//Aptio Server Override Start
/*
#include "amlresrc.h" // came from https://acpica.org/downloads/source_code.php acpica-win-20130214.zip/source/include
#include <IndustryStandard/AcpiAml.h>

*/
//Aptio Server Override End
#ifdef BDAT_SUPPORT
#include "bdat.h"
EFI_GUID gEfiMemoryMapDataHobBdatGuid  = BDAT_MEMORY_DATA_4B_GUID;
EFI_GUID gEfiRmtDataHobBdatGuid        = RMT_SCHEMA_5_GUID;
#endif
//
// Include AML offset header files generated by iASL.  This is used for patching DSDT during POST.
//
//#include "SRPPlatform.offset.h"  //AptioV server override

#ifndef MAX_HOB_ENTRY_SIZE
#define MAX_HOB_ENTRY_SIZE  60*1024
#endif

#pragma optimize("",off)
extern EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *mSpcrTable;
extern EFI_PLATFORM_INFO           *mPlatformInfo;
extern BIOS_ACPI_PARAM             *mAcpiParameter;
extern struct SystemMemoryMapHob   *mSystemMemoryMap;
extern EFI_IIO_UDS_PROTOCOL        *mIioUds;
extern EFI_CPU_CSR_ACCESS_PROTOCOL *mCpuCsrAccess;
extern BOOLEAN                     mX2ApicEnabled;
extern SYSTEM_CONFIGURATION        mSystemConfiguration;

extern UINT64 OemDsdtTblId;  // AptioV Server Override: Added AMI DSDT OemTableId identification
static BOOLEAN                     mCpuOrderSorted = FALSE;
static EFI_GUID gSetupGuid = SETUP_GUID; // AptioV server override: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.
EFI_MPST_SUPPORT_PROTOCOL          mMpstSupport;
EFI_ACPI_MEMORY_POWER_NODE         mMemoryPowerNodeTemplate;
UINT16                             mMemoryPowerNodeStrucId; // MPST Power node structure ID and at the end contains the number of MPN structures cretaed.
UINT16                             mMainMemoryPowerNodeId;  // Memory power node ID pointed by power node structure
UINT32                             mPowerConsumed[EFI_ACPI_MEMORY_POWER_STATES_COUNT];   // milli watts
UINT64                             mPrevEnergyConsumed[EFI_ACPI_MEMORY_POWER_NODES_COUNT];
UINT64                             mPrevPcctEnergyValue[EFI_ACPI_MEMORY_POWER_NODES_COUNT];
UINT64                             mOverflowCnt[EFI_ACPI_MEMORY_POWER_NODES_COUNT];
UINT64                             mAddOffset[EFI_ACPI_MEMORY_POWER_NODES_COUNT];
UINT64                             mSubOffset[EFI_ACPI_MEMORY_POWER_NODES_COUNT];
UINT32                             mNumOfBitShift;

//
// Keep track of relationship between node/channel ID and memory power
// management information.
//
typedef struct {
  UINT16  ChId:4;
  UINT16  NodeId:4;
  UINT16  MemoryNodeId:4;
  UINT16  PowerManagedFlag:4;
} NODE_CH_PWR_MEM_INFO;

//
// Global for the CPU I/O Protocol that is consumed by this driver
//
EFI_CPU_IO_PROTOCOL           *mCpuIo;

EFI_CPU_ID_ORDER_MAP           mCpuApicIdOrderTable[MAX_CPU_NUM];

UINT32 mCpuIndexTable[MAX_THREAD * MAX_CORE];

UINT32
AcpiProcessorId2ApicId (
  UINT32  AcpiProcessorId
  )
{
  UINTN Index;

  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
    if (mCpuApicIdOrderTable[Index].Flags && (mCpuApicIdOrderTable[Index].AcpiProcessorId == AcpiProcessorId)) {
      return mCpuApicIdOrderTable[Index].ApicId;
    }
  }
  return (UINT32) -1;
}

UINT32
ApicId2AcpiProcessorId (
  UINT32  ApicId
  )
{
  UINTN Index;

  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
    if (mCpuApicIdOrderTable[Index].Flags && (mCpuApicIdOrderTable[Index].ApicId == ApicId)) {
      return mCpuApicIdOrderTable[Index].AcpiProcessorId;
    }
  }

  return (UINT32) -1;
}

UINT32
SwProcApicId2AcpiProcId (
  UINT32 CpuIndex
  )
{
  UINTN Index;

  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
    if ((mCpuApicIdOrderTable[Index].Flags == 1) && (mCpuApicIdOrderTable[Index].SwProcApicId == CpuIndex)) {
      return mCpuApicIdOrderTable[Index].AcpiProcessorId;
    }
  }
  
  //if not found, then use BSP data
  return (UINT32) -1;
}

UINT32
ApicId2SwProcApicId (
  UINT32 ApicId
  )
{
  UINT32 Index;

  for (Index = 0; Index < MAX_CPU_NUM; Index++) {
    if ((mCpuApicIdOrderTable[Index].Flags == 1) && (mCpuApicIdOrderTable[Index].ApicId == ApicId)) {
      return Index;
    }
  }

  return (UINT32) -1;

}

EFI_STATUS
LocateCpuEistInfo (
  IN   UINT32                        CpuIndex,
  OUT  CPU_MISC_DATA                 **CpuMiscData
  )
{
  UINTN                       Index;
  UINT32                      ApicId;

  ApicId = AcpiProcessorId2ApicId (CpuIndex);
  if (ApicId == (UINT32) -1) {
	if(CpuIndex == 0) { //assuming use SBSP info
	   ApicId = mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[CpuIndex].CpuMiscData.ApicID;
	} else {
           *CpuMiscData = NULL;
           return EFI_NOT_FOUND;
        }
  }

  for (Index = 0; Index < mCpuConfigLibConfigContextBuffer->NumberOfProcessors; Index++) {
    if (mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[Index].CpuMiscData.ApicID == ApicId) {
      *CpuMiscData = &mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[Index].CpuMiscData;
      return EFI_SUCCESS;
    }
  }

  *CpuMiscData = NULL;
  return EFI_NOT_FOUND;
}

EFI_STATUS
PlatformHookInit (
  VOID
  )
{
  //
  // If Emulation flag set by InitializeDefaultData in MemoryQpiInit.c
  //  force X2APIC
  // Else read setup data
  //
  if (mPlatformInfo->Emulation == VP_FLAG) {
    mX2ApicEnabled = 1 ;
  } else {
  mX2ApicEnabled = mSystemConfiguration.ProcessorXapic;
  }
  return EFI_SUCCESS;
}

EFI_ACPI_TABLE_VERSION
AcpiPlatformHooksGetAcpiTableVersion (
  VOID
  )
/*++

Routine Description:

  Returns the ACPI table version that the platform wants.

Arguments:

  None

Returns:

  EFI_ACPI_TABLE_VERSION_NONE if ACPI is to be disabled
  EFI_ACPI_TABLE_VERSION_1_0B if 1.0b
  EFI_ACPI_TABLE_VERSION_2_00 if 2.00
--*/
{
  //
  // If the platform wants to dynamically control ACPI version including disabling,
  // read the setup variable, and return the data returned by the variable
  //
  // return  EFI_ACPI_TABLE_VERSION_1_0B;
  // return  EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0;
  //
  return EFI_ACPI_TABLE_VERSION_2_0;
}

EFI_STATUS
AcpiPlatformHooksGetOemFields (
  OUT UINT8   *OemId,
  OUT UINT64  *OemTableId,
  OUT UINT32  *OemRevision
  )
/*++

Routine Description:

  Returns the OEMID, OEM Table ID, OEM Revision.

Arguments:

  None

Returns:
  OemId      - OEM ID string for ACPI tables, maximum 6 ASCII characters.
               This is an OEM-supplied string that identifies the OEM.
  OemTableId - An OEM-supplied string that the OEM uses to identify 
               the particular data table. This field is particularly useful 
               when defining a definition block to distinguish definition block 
               functions. The OEM assigns each dissimilar table a new OEM Table ID.
  OemRevision - An OEM-supplied revision number for ACPI tables. 
                Larger numbers are assumed to be newer revisions.

--*/

//
// GC_TODO:    EFI_SUCCESS - add return value to function comment
//
{
  UINT64                TempOemId, TempOemTableId;

  TempOemId      = PcdGet64(PcdAcpiOemId);
  TempOemTableId = PcdGet64(PcdAcpiTableOemId);
  
  CopyMem (&OemId, &TempOemId, 6);
  CopyMem (&OemTableId, &TempOemTableId, 8);
  
  *OemRevision  = EFI_ACPI_OEM_REVISION;
  return EFI_SUCCESS;
}

EFI_STATUS
AcpiPlatformHooksIsActiveTable (
  IN OUT EFI_ACPI_COMMON_HEADER     *Table
  )
/*++

Routine Description:

  Called for every ACPI table found in the BIOS flash.
  Returns whether a table is active or not. Inactive tables
  are not published in the ACPI table list. This hook can be
  used to implement optional SSDT tables or enabling/disabling
  specific functionality (e.g. SPCR table) based on a setup
  switch or platform preference. In case of optional SSDT tables,
  the platform flash will include all the SSDT tables but will
  return EFI_SUCCESS only for those tables that need to be
  published. 

Arguments:

  *Table - Pointer to the active table

Returns:

  Status  - EFI_SUCCESS if the table is active
  Status  - EFI_UNSUPPORTED if the table is not active
--*/
{
  EFI_ACPI_DESCRIPTION_HEADER     *TableHeader;

  TableHeader   = (EFI_ACPI_DESCRIPTION_HEADER *) Table;

  // 4167995: We ought not be publishing Mpst when Numa is enabled - Added NumaEn check below
  if (TableHeader->Signature == EFI_ACPI_2_0_MEMORY_POWER_STATE_TABLE_SIGNATURE) {
    if ((mSystemMemoryMap == NULL) || (mSystemConfiguration.Mpst == 0) || (mSystemConfiguration.NumaEn == NUMA_DIS))
      return EFI_NOT_FOUND;
  }

  if (TableHeader->Signature == EFI_ACPI_2_0_PMTT_TABLE_SIGNATURE) {
    if ((mSystemMemoryMap == NULL) || (mSystemConfiguration.Mpst == 0))
      return EFI_NOT_FOUND;
  }

  if (TableHeader->Signature == EFI_ACPI_3_0_PCTT_SIGNATURE) {
    if ((mSystemMemoryMap == NULL) || (mSystemConfiguration.Mpst == 0))
      return EFI_NOT_FOUND;
  }

#ifdef BDAT_SUPPORT
  if (TableHeader->Signature == EFI_BDAT_TABLE_SIGNATURE) {
    if (mSystemConfiguration.bdatEn == 0)
      return EFI_NOT_FOUND;
  }
#endif

  if (TableHeader->Signature  ==  EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE) {
    //
    // Initialize the SPCR table pointer.
    // SPCR table is not ready yet, update it before booting.
    //
    mSpcrTable = (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *) Table;
    return EFI_NOT_READY;
  }

  if ((TableHeader->Signature == EFI_ACPI_2_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE)    ||
      (TableHeader->Signature == EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE) ||
      (TableHeader->Signature == EFI_ACPI_4_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE)) {
    // Only publish SRAT/SLIT/MSCT if systememorymap available and Numa is enabled in Setup.
    if ((mSystemMemoryMap == NULL) || (mSystemConfiguration.NumaEn == 0))
      return EFI_NOT_FOUND;
  }

#ifndef  GRANGEVILLE_FLAG
	//NITRO
	if(TableHeader->Signature == NITRO_TABLE_SIGNATURE)	//AptioV server override
  {
  
    if((mPlatformInfo->BoardId == TypeHedtSKU1CRB) ||
       (mPlatformInfo->BoardId == TypeHedtEv)      ||
       (mPlatformInfo->BoardId == TypeHedtDDR3)    ||
       (mPlatformInfo->BoardId == TypeAztecCityCRBSRP)
       ){
         if (mAcpiParameter->NitrousNotSupport == 0) {
           return EFI_SUCCESS;    // Support
         } else {
           return EFI_NOT_FOUND;  // Not support
         }
    }
  }
#endif

  if (TableHeader->Signature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {

 // AptioV server override start - Added AMI DSDT OemTableId identification
    if (0 == CompareMem (&(TableHeader->OemTableId), &OemDsdtTblId, 8) ) {
      DEBUG(( EFI_D_ERROR, "AcpiPlatform: Using AMI DSDT. \n"));
      return EFI_SUCCESS;    
    } 
// AptioV server override end

#ifndef GRANGEVILLE_FLAG
		  if ( (0 == CompareMem (&(TableHeader->OemTableId), "PLATFSRP", 8)) &&
			   ((mPlatformInfo->BoardId == TypeMayanCitySRP) || 
			   (mPlatformInfo->BoardId == TypeMayanCitySRPDDR3) ||
			   (mPlatformInfo->BoardId == TypeYakimaCitySRP) ||
			   (mPlatformInfo->BoardId == TypeYakimaCitySTHI) ||
			   (mPlatformInfo->BoardId == TypeAztecCitySTHI) ||
			   (mPlatformInfo->BoardId == TypeIncaCitySRP) ||
			   (mPlatformInfo->BoardId == TypeHalfWidthCitySRP)) ) {
#else
	  if ( (0 == CompareMem (&(TableHeader->OemTableId), "PLATFSRP", 8)) &&
			   (
			   (mPlatformInfo->BoardId == TypeBeverlyCoveCRB) ||
			   (mPlatformInfo->BoardId == TypeBeverlyCoveSODimmCRB) ||
         (mPlatformInfo->BoardId == TypeCamelbackMountain) ||
         (mPlatformInfo->BoardId == TypeTlaquepaque) || 
			   (mPlatformInfo->BoardId == TypeTrabucoCanyon)||
			     (mPlatformInfo->BoardId == TypePiestewaPeak)) ) {  
#endif

      DEBUG(( EFI_D_ERROR, "AcpiPlatform Platform SRP: Using SRP DSDT\n"));
      return EFI_SUCCESS;    
    } 


#ifndef GRANGEVILLE_FLAG
    if ( (0 == CompareMem (&(TableHeader->OemTableId), "PLATFSRP", 8)) &&
         ((mPlatformInfo->BoardId == TypeMayanCityCRB) || 
         (mPlatformInfo->BoardId == TypeMayanCityCRBDDR3) ||
         (mPlatformInfo->BoardId == TypeWildcatPass) ||
         (mPlatformInfo->BoardId == TypeYakimaCityCRB) ||
         (mPlatformInfo->BoardId == TypeAztecCityCRBSRP) ||
         (mPlatformInfo->BoardId == TypeIncaCityCRB) ||
         (mPlatformInfo->BoardId == TypeHedtSKU1CRB) ||
         (mPlatformInfo->BoardId == TypeHedtEv) ||
         (mPlatformInfo->BoardId == TypeEmeraldPoint) || 
         (mPlatformInfo->BoardId == TypeHedtDDR3)) ) {
#else
if ( (0 == CompareMem (&(TableHeader->OemTableId), "PLATFSRP", 8)) &&
		 (
		 (mPlatformInfo->BoardId == TypeBeverlyCoveCRB) ||
		 (mPlatformInfo->BoardId == TypeBeverlyCoveSODimmCRB) ||
     (mPlatformInfo->BoardId == TypeCamelbackMountain) ||
     (mPlatformInfo->BoardId == TypeTlaquepaque) || 
     (mPlatformInfo->BoardId == TypeTrabucoCanyon) ||
     (mPlatformInfo->BoardId == TypePiestewaPeak)) ) { 
#endif

      DEBUG(( EFI_D_ERROR, "AcpiPlatform Platform SRP: Using CRB DSDT\n"));
      return EFI_SUCCESS;
    }
    return EFI_UNSUPPORTED;
  }
  return EFI_SUCCESS;
}

BOOLEAN
IsTurboModeEnabled (
    VOID
  )
{
  EFI_CPUID_REGISTER     CpuidRegisters;
  BOOLEAN                Status;
  UINT64                 MsrValue;

  Status = FALSE;
  AsmCpuid (EFI_CPUID_POWER_MANAGEMENT_PARAMS, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
  if ((CpuidRegisters.RegEax & EFI_CPUID_POWER_MANAGEMENT_EAX_TURBO) != 0) {
    //
    // Turbo mode is supported on this processor (Available and Visible)
    //
    MsrValue = AsmReadMsr64 (EFI_MSR_IA32_MISC_ENABLE);

    if (!(MsrValue & B_EFI_MSR_IA32_MISC_DISABLE_TURBO)) {
      //
      // Turbo mode is supported on this processor (Available but Hidden)
      //
      Status = TRUE;
    }
  }

  return Status;

}
BOOLEAN
	IsTurboModeSupported (
    VOID
  )
{
  EFI_CPUID_REGISTER     CpuidRegisters;
  BOOLEAN                Status;
                   

  Status = FALSE;
  AsmCpuid (EFI_CPUID_POWER_MANAGEMENT_PARAMS, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
  if ((CpuidRegisters.RegEax & EFI_CPUID_POWER_MANAGEMENT_EAX_TURBO) != 0) {
      //
      // Turbo mode is supported on this processor (Available but Hidden)
      //
      Status = TRUE;
   
  }

  return Status;

}

// AptioV server override start: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.
VOID
FixupSystemSleepStates (
	  VOID
  )
/*++

  Routine Description: 

    For each sleep state passed in, determine if it should be enabled/disabled

  Arguments:              

    SleepStateForFixup - Integer 3 or 4 representing S3, or S4

  Returns:                

    UINT32 - Returns 0/1

--*/
{
  EFI_STATUS Status;
  SETUP_DATA SetupData;
  UINTN Size = sizeof(SETUP_DATA);
  UINT32 AcpiSleepState = 0;    // 0 = no sleep states, 1 = S1, 2 = S1/S3
  //UINT32 AcpiS1Enable   = 1;
 // UINT32 AcpiS3Enable   = 1;
  //UINT32 AcpiS4Enable   = 1;
  
  Status = gRT->GetVariable (L"Setup", &gSetupGuid, NULL, &Size, &SetupData);
  //
  // If read Setup OK previously, update our variables
  //  else they are left with defaults as initialized
  //
  /*
  if (NULL != &mSystemConfiguration) {
    AcpiSleepState = mSystemConfiguration.AcpiSleepState;

  }
*/
  AcpiSleepState = SetupData.AcpiSleepState;
  /*if (AcpiSleepState == 1) {
	  mAcpiParameter->AcpiS1Enable = 1;
	  mAcpiParameter->AcpiS3Enable= 0;
	  
  }*/
  if (AcpiSleepState == 2){
         //
         // If S1/S3 is disabled by the only Setup knob
         //  available to CRB, follow that knob
         //
	mAcpiParameter->AcpiS3Enable = 1;
#ifndef GRANGEVILLE_FLAG
	 		if ( (mPlatformInfo->BoardId == TypeYakimaCitySRP) ||
 			   (mPlatformInfo->BoardId == TypeYakimaCitySTHI) ||
 			   (mPlatformInfo->BoardId == TypeYakimaCityCRB) ||
 			   (mPlatformInfo->BoardId == TypeIncaCitySRP) ||
 			   (mPlatformInfo->BoardId == TypeIncaCityCRB) )
			   {
 		#else
			if (
				 (mPlatformInfo->BoardId == TypeBeverlyCoveCRB))  {
		#endif		 
 				 mAcpiParameter->AcpiS3Enable= 0;
               }
	   }
   else
	   {
	        mAcpiParameter->AcpiS3Enable=0;
	   }
        
  mAcpiParameter->AcpiS4Enable=SetupData.AcpiHibernate;

  /*
  switch (SleepStateForFixup) {
    //
    // Handle S1
    //
    case 1:
      //
      // If S3 is disabled by the only Setup knob
      //  available to CRB, force enable S1
      //
      if (1 == AcpiSleepState) {
         AcpiS1Enable = 1;
      } else {
          //
          // If S1/S3 is disabled by the only Setup knob
          //  available to CRB, follow that knob
          //
         if (0 == AcpiSleepState) {
         AcpiS1Enable = 0;
      }
       }

      return AcpiS1Enable;
      break;

    //
    // Handle S3
    //
    case 3:
      //
      // If S3 is disabled by the only Setup knob
      //  available to CRB, follow that knob
      //
      if (AcpiSleepState < 2) {
        AcpiS3Enable = 0;
      }

      //
      // Check for platforms that don't support S3
      //

			if ( (mPlatformInfo->BoardId == TypeYakimaCitySRP) ||
			   (mPlatformInfo->BoardId == TypeYakimaCitySTHI) ||
			   (mPlatformInfo->BoardId == TypeYakimaCityCRB) ||
			   (mPlatformInfo->BoardId == TypeIncaCitySRP) ||
			   (mPlatformInfo->BoardId == TypeIncaCityCRB) ) {
		
        AcpiS3Enable = 0;
      }

      return AcpiS3Enable;
      break;

    //
    // Handle S4
    //
    case 4:
      return AcpiS4Enable;
      break;

    //
    // Default return
    //
    default:
      return 0;
      break;
  }*/
 
}
// AptioV server override end: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.  

EFI_STATUS
PatchGv3SsdtTable (
  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader
  )
/*++

  Routine Description: 

    Update the GV3 SSDT table

  Arguments:              

    *TableHeader   - The table to be set

  Returns:                

    EFI_SUCCESS -  Returns Success

--*/
{
  EFI_STATUS                  Status;
  UINT8                       *CurrPtr;
  UINT8                       *SsdtPointer;
  UINT32                      Signature;
  UINT32                      CpuFixes;
  UINT32                      NpssFixes;
//  UINT32                      SpssFixes;
  UINT32                      CpuSkt;
  UINT32                      CpuIndex;
  UINT32                      ThreadIndex;
  UINT32                      CpuEnabled;
  UINT32                      AcpiProcId;
  UINT32                      PackageSize;
  UINT32                      NewPackageSize;
  UINT32                      AdjustSize;
  UINTN                       TableIndex;
  EFI_ACPI_NAME_COMMAND       *PssTable;
  EFI_PSS_PACKAGE             *PssTableItemPtr;
  CPU_MISC_DATA               *CpuMiscData;
  EFI_ACPI_NAMEPACK_DWORD     *NamePtr;
  EFI_CPUID_REGISTER          CpuidRegisters;
  UINT32                      BspApicID;
  FVID_ENTRY                  *PssState;
  UINT8                       DOMNValue; 
  UINT8                       NCPUValue;
  UINT8                       HWALValue;
  UINT32                      AcpiApicId;
  EFI_ACPI_NAME_COMMAND       *PsdPackage;
  PSD_PACKAGE_LAYOUT          *PsdPackageItemPtr;
  UINT8                        MaxOCRatio = 0x00;
  BOOLEAN                    Supported=FALSE;
  

  //
  // Loop through the ASL looking for values that we must fix up.
  //
  DOMNValue = 0;
  NCPUValue = 0;
  HWALValue = 0;
  NpssFixes = 0;
//  SpssFixes = 0;
  CpuFixes  = 0;
  CpuSkt    = 0;
  CpuIndex  = 0;
  ThreadIndex = 0;
  AcpiProcId = 0;
  AcpiApicId = 0;
  CurrPtr   = (UINT8 *) TableHeader;

  CpuEnabled = mPlatformInfo->CpuData.CpuPCPSInfo & 0xFF;

  AsmCpuid (EFI_CPUID_VERSION_INFO, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
  BspApicID =  (UINT32)(CpuidRegisters.RegEbx >> 24);
  CpuIndex = ApicId2AcpiProcessorId(BspApicID);
  Status = LocateCpuEistInfo (CpuIndex, &CpuMiscData);
  if( (EFI_ERROR (Status)) || (CpuMiscData == NULL ) ){
    DEBUG ((EFI_D_ERROR, " PatchGv3SsdtTable - EIST info for BSP index not found \n"));
    return Status;
  }
  DEBUG((EFI_D_ERROR, ":::: mPlatformInfo->CpuData.CpuPCPSInfo = %x\n", mPlatformInfo->CpuData.CpuPCPSInfo));
  DEBUG((EFI_D_ERROR, ":::: mSystemConfiguration.ProcessorEistPsdFunc = %x\n", mSystemConfiguration.ProcessorEistPsdFunc));

  // PCPS - Update HWAL and NCPU
  HWALValue = (UINT8) mSystemConfiguration.ProcessorEistPsdFunc;

  if ((mPlatformInfo->CpuData.CpuPCPSInfo & B_PCPS_SPD_ENABLE) && mSystemConfiguration.ProcessorSPD){
    if (mSystemConfiguration.PStateDomain) {
        NCPUValue = (UINT8) CpuEnabled; //mPlatformInfo->CpuData.CpuPCPSInfo & 0xFF;
    } else {
      if (mPlatformInfo->CpuData.CpuPCPSInfo & B_PCPS_HT_ENABLE) {
        NCPUValue = 2;
      } else {
        NCPUValue = 1;
      }
    }
    
/* Aptio V Server Override - setup question ProcessorSinglePCTLEn is removed, and this function is not used.

    if ((mSystemConfiguration.ProcessorSinglePCTLEn) && (!mSystemConfiguration.PStateDomain)) {
        HWALValue = 2;  //force SW_ANY
    } 

    if (mSystemConfiguration.ProcessorSinglePCTLEn == 2) {
        HWALValue = 1;  //force SW_ALL
    } 
*/
  } else {
    if (mSystemConfiguration.PStateDomain) {
        NCPUValue = (UINT8) CpuEnabled; //mPlatformInfo->CpuData.CpuPCPSInfo & 0xFF;
    } else {
        NCPUValue = 1;
    }
  }

  for (SsdtPointer = CurrPtr; SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); SsdtPointer++) {
    Signature = *(UINT32 *) SsdtPointer;
    switch (Signature) {
      case SIGNATURE_32 ('_', 'S', 'B', '_'):
        //SKTX
        CpuSkt = *(SsdtPointer + 7);
        if(CpuSkt >= '0' && CpuSkt <= '3') {
          CpuSkt -= '0';

          //
          // _PRXX ('00 to 013')
          //
          CpuIndex = *(SsdtPointer + 11);
          if( *(SsdtPointer + 10) == '0') {
            if ((CpuIndex >= '0') && (CpuIndex <= '9')) {
              CpuIndex -= '0';
            } else if ((CpuIndex >= 'A') && (CpuIndex <= 'F')) {
              CpuIndex = 10 + (CpuIndex - 'A');
            }  
          } else if( *(SsdtPointer + 10) == '1')  { //is 0x10 - 0x1F
            if ((CpuIndex >= '0') && (CpuIndex <= '9')) {//must be 0x10 - 0x19
              CpuIndex = 0x10 + (CpuIndex - '0');
            } else if ((CpuIndex >= 'A') && (CpuIndex <= 'F')){ //must be 0x1A - 0x1F
              CpuIndex = 0x1A + (CpuIndex - 'A');
            }
          } else { //must be 0x20 - 0x2F
            if ((CpuIndex >= '0') && (CpuIndex <= '9')) {//must be 0x20 - 0x29
              CpuIndex = 0x20 + (CpuIndex - '0');
            } else if ((CpuIndex >= 'A') && (CpuIndex <= 'F')){ //must be 0x2A - 0x2F
              CpuIndex = 0x2A + (CpuIndex - 'A');
            }
          } 
          
          ThreadIndex = CpuIndex;

          //CpuIndex format Socket#:Thread# [2:6] - sypport up to 144 threads/socket
          // matching SSDT table
          CpuIndex = (CpuSkt << mNumOfBitShift) + (CpuIndex & THREAD_MASK_64);
        }

        // PCPS - Update DOMN
        DOMNValue = (UINT8) CpuSkt;

        if ((mPlatformInfo->CpuData.CpuPCPSInfo & B_PCPS_SPD_ENABLE) && mSystemConfiguration.ProcessorSPD){
          if (mSystemConfiguration.PStateDomain == 0) {
              //DOMNValue = (UINT8) CpuIndex >> 1;
              DOMNValue = (UINT8) (((CpuEnabled * CpuSkt) + ThreadIndex) >> 1);
          }      
        } else {
          if (mSystemConfiguration.PStateDomain == 0) {
              //DOMNValue = (UINT8) CpuIndex;
              DOMNValue = (UINT8) ((CpuEnabled * CpuSkt) + ThreadIndex);
          }
        }

        DEBUG ((EFI_D_ERROR, "\n::ACPI:: [%d]  CpuIndex: %x,   NCPUValue = %d,  HWALValue = %x,   DOMNValue = %x\n  ", \
                             CpuFixes, CpuIndex, NCPUValue, HWALValue, DOMNValue));
        CpuFixes++;
        LocateCpuEistInfo (0, &CpuMiscData);  //use CPU0 for update NPSS and SPSS 
        break;

      case SIGNATURE_32 ('D', 'O', 'M', 'N'):

        NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
        if (NamePtr->StartByte != AML_NAME_OP) {
          continue;
        } 

        if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
          continue;
        }

        NamePtr->Value = (UINT32) DOMNValue; 
        break;

      case SIGNATURE_32 ('N', 'C', 'P', 'U'):

        NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
        if (NamePtr->StartByte != AML_NAME_OP) {
          continue;
        }

        if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
          continue;
        }

        NamePtr->Value = (UINT32) NCPUValue; 
        break;

      case SIGNATURE_32 ('H', 'W', 'A', 'L'):

        NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
        if (NamePtr->StartByte != AML_NAME_OP) {
          continue;
        }

        if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
          continue;
        }

        NamePtr->Value = (UINT32) HWALValue; 
        break;

      case SIGNATURE_32 ('P', 'S', 'D', 'C'):
      case SIGNATURE_32 ('P', 'S', 'D', 'D'):
      case SIGNATURE_32 ('P', 'S', 'D', 'E'):

        PsdPackage = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
        if (PsdPackage->StartByte != AML_NAME_OP) {
          continue;
        }
  
        PsdPackageItemPtr       = (PSD_PACKAGE_LAYOUT *) ((UINT8 *) PsdPackage);
        //DEBUG((EFI_D_ERROR, "\n:::: PRINT PsdPackageItemPtr table:     %x   is detected...\n", PsdPackage->NameStr));
        //DEBUG((EFI_D_ERROR, "::::                                   Domain = %x,    CoordType = %x,   NumProcessors = %x\n", PsdPackageItemPtr->Domain, PsdPackageItemPtr->CoordType, PsdPackageItemPtr->NumProcessors ));

        PsdPackageItemPtr->Domain = DOMNValue;
        //PsdPackageItemPtr->CoordType = HWALValue;
        PsdPackageItemPtr->NumProcessors = NCPUValue;
        SsdtPointer = (UINT8 *) PsdPackage + sizeof (EFI_ACPI_NAME_COMMAND) + sizeof (EFI_PSD_PACKAGE);
        //DEBUG((EFI_D_ERROR, "::::  PsdPackage = %x,    PsdPackageItemPtr = %x,   SsdtPointer = %x\n", (UINT8 *)PsdPackage, (UINT8 *)PsdPackageItemPtr, (UINT8 *)SsdtPointer ));
        //DEBUG((EFI_D_ERROR, "::::      Updated  Domain = %x,    CoordType = %x,   NumProcessors = %x\n", PsdPackageItemPtr->Domain, PsdPackageItemPtr->CoordType, PsdPackageItemPtr->NumProcessors ));

        break;

      case SIGNATURE_32 ('N', 'P', 'S', 'S'):
      case SIGNATURE_32 ('S', 'P', 'S', 'S'):

        PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
        if (PssTable->StartByte != AML_NAME_OP) {
          continue;
        }
  
        ASSERT (CpuMiscData != NULL);
        PssState = CpuMiscData->FvidTable;

        AdjustSize  = PssTable->NumEntries * sizeof (EFI_PSS_PACKAGE);
        AdjustSize -= (UINT32)(CpuMiscData->NumberOfPStates * sizeof (EFI_PSS_PACKAGE));
        PackageSize     = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4);
        NewPackageSize  = PackageSize - AdjustSize;
        PssTable->Size  = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4));
  
        //
        // Set most significant two bits of byte zero to 01, meaning two bytes used
        //
        PssTable->Size |= 0x40;
  
        //
        // Set unused table to Noop Code
        //
        SetMem (
          (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE,
          AdjustSize,
          AML_NOOP_OP
          );
        PssTable->NumEntries  = (UINT8) CpuMiscData->NumberOfPStates;
        PssTableItemPtr       = (EFI_PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (EFI_ACPI_NAME_COMMAND));

        //
        // Update the size
        //
        //DEBUG ((EFI_D_ERROR, "Frequecy   Power   Latency  MsterLat  Control   Status\n"));
		Supported=IsTurboModeSupported();
        for (TableIndex = 0; TableIndex < CpuMiscData->NumberOfPStates; TableIndex++) {
          if (mSystemConfiguration.TurboMode && (TableIndex == 0) && (Supported)) {
		   	DEBUG ((EFI_D_ERROR, ":::Turbo supported   ::: \n"));
            PssTableItemPtr->CoreFreq = (UINT32)((CpuMiscData->IntendedFsbFrequency * PssState[TableIndex + 1].Ratio) + 1);
          } else {
            PssTableItemPtr->CoreFreq = (UINT32)(CpuMiscData->IntendedFsbFrequency * PssState[TableIndex].Ratio);
          }

          //if (CpuFixes == 1) {
          //  DEBUG ((EFI_D_ERROR, "[%d] %d\n", TableIndex, PssTableItemPtr->CoreFreq));
          //}

          PssTableItemPtr->Power    =  (UINT32)(PssState[TableIndex].Power); // when calulate Tdp already make it mW;
          if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
            PssTableItemPtr->TransLatency = (UINT32)(PssState[TableIndex].TransitionLatency);
			
			if((TableIndex == 0x00 ) && (mSystemConfiguration.OverclockingSupport))
			{
			  
			  ReadOcCap(&MaxOCRatio);
			  if(MaxOCRatio != 0x00)
			  PssState[TableIndex].Ratio = MaxOCRatio;
			  
			}
              PssTableItemPtr->Control  = (UINT32)(PssState[TableIndex].Ratio << 8);
              PssTableItemPtr->Status   = (UINT32)(PssState[TableIndex].Ratio << 8);
          } else {
            //
            // This method should be supported by SMM PPM Handler
            //
            // Status is simply the state number.
            // Use the state number w/ OS command value so that the
            // legacy interface may be used.  Latency for SMM is 100 + BM latency.
            PssTableItemPtr->Status   = (UINT32)TableIndex;
            PssTableItemPtr->TransLatency = (UINT32)(100 + PssState[TableIndex].TransitionLatency);
            PssTableItemPtr->Control  = (UINT32)(SW_SMI_OS_REQUEST | (TableIndex << 8));
          }

          PssTableItemPtr->BMLatency    = (UINT32)(PssState[TableIndex].BusMasterLatency);

          if (CpuFixes == 1) {
            DEBUG ( (EFI_D_ERROR, "::ACPI TBL:: P%d:  PssTableItemPtr->CoreFreq, Power, TransLatency, BMLatency, Control, Status = %x\n", \
              TableIndex, \
              PssTableItemPtr->CoreFreq, \
              PssTableItemPtr->Power, \
              PssTableItemPtr->TransLatency, \
              PssTableItemPtr->BMLatency, \
              PssTableItemPtr->Control, \
              PssTableItemPtr->Status, \
              PssTableItemPtr->CoreFreq
            ) );
          }

          PssTableItemPtr++;
        }
  
        if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
          NpssFixes++;
        } //else {
          //SpssFixes++;
        //}

        SsdtPointer = (UINT8 *) PssTable + PackageSize;
        break;
    } // switch
  } // for
  
  //
  // N fixes together currently
  //
  //ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM); // AptioV server override
//  ASSERT (SpssFixes == NpssFixes);
//  ASSERT (CpuFixes >= SpssFixes);

  return EFI_SUCCESS;
}

EFI_STATUS
PatchDsdtTable (
  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader
  )
/*++

  Routine Description: 

    Update the DSDT table

  Arguments:              

    *TableHeader   - The table to be set

  Returns:                

    EFI_SUCCESS - DSDT updated
    EFI_INVALID_PARAMETER - DSDT not updated

--*/
{
  EFI_STATUS Status;
  UINT8   *DsdtPointer;
  UINT32  *Signature;
  UINT32  Fixes, NodeIndex;
  UINT8   Counter, i;
  UINT8   BusBase_Iio[MAX_SOCKET] = {0x00, 0x00, 0x00, 0x00}, BusLimit_Iio[MAX_SOCKET] = {0xFE, 0xFE, 0xFE, 0xFE}, BusBase_Uncore[MAX_SOCKET] = {0xFF, 0xFF, 0xFF, 0xFF};
  UINT16  IoBase_Iio[MAX_SOCKET]    = {0, 0, 0, 0}, IoLimit_Iio[MAX_SOCKET]    = {0, 0, 0, 0};
  UINT32  MemBase32_Iio[MAX_SOCKET] = {0, 0, 0, 0}, MemLimit32_Iio[MAX_SOCKET] = {0, 0, 0, 0};
  UINT64  MemBase64_Iio[MAX_SOCKET] = {0, 0, 0, 0}, MemLimit64_Iio[MAX_SOCKET] = {0, 0, 0, 0};
  UINT64  MemoryBaseLimit = 0;
  UINT64  PciHGPEAddr = 0;
  UINT64  BusDevFunc = 0;
  UINT64  PcieHpBus             = 0;
  UINT64  PcieHpDev             = 0;
  UINT64  PcieHpFunc            = 0;
  UINT64  IioBusIndex = 0;

  UINT32 CpuCount = 0, CpuSkt = 0, CpuIndex = 0; 
  EFI_ACPI_NAMEPACK_DWORD     *NamePtr;
  UINT8   *CurrPtr;
  Status = EFI_SUCCESS;
  mAcpiParameter->MemoryBoardBitMask = 0;

  for (i = 0 ; i < MAX_SOCKET ; i++) {
    if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].Valid) {
      BusBase_Uncore[i] = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[i].BusNum;
    }
    if (((mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].BusBase) <= (mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].BusLimit)) && (mIioUds->IioUdsPtr->PlatformData.IioQpiInfo[i].Valid)) {
      BusBase_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].BusBase;
      BusLimit_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].BusLimit - 1;
      IoBase_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].PciResourceIoBase;
      IoLimit_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].PciResourceIoLimit;
      MemBase32_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].PciResourceMem32Base;
      MemLimit32_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].PciResourceMem32Limit;
      //AptioV server override start: Fix for Windows x86 OS installation failure
      if (mIioUds->IioUdsPtr->PlatformData.Pci64BitResourceAllocation) { 
	      MemBase64_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].PciResourceMem64Base;	
	      MemLimit64_Iio[i] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[i].PciResourceMem64Limit;
      }    
      //AptioV server override end: Fix for Windows x86 OS installation failure
    }
  }

  for(Counter = 0; Counter < mSystemMemoryMap->numberEntries; Counter++) {
    NodeIndex = mSystemMemoryMap->Element[Counter].NodeId;
    if((mAcpiParameter->MemoryBoardBitMask) & (1 << NodeIndex)){
      MemoryBaseLimit = mAcpiParameter->MemoryBoardRange[NodeIndex] + LShiftU64(mSystemMemoryMap->Element[Counter].ElementSize, MEM_ADDR_SHFT_VAL);
      mAcpiParameter->MemoryBoardRange[NodeIndex] = MemoryBaseLimit;
    } else {
      mAcpiParameter->MemoryBoardBitMask |= 1 << NodeIndex;
      MemoryBaseLimit = LShiftU64(mSystemMemoryMap->Element[Counter].BaseAddress, 30);
      mAcpiParameter->MemoryBoardBase[NodeIndex] = MemoryBaseLimit;
      MemoryBaseLimit = LShiftU64((mSystemMemoryMap->Element[Counter].BaseAddress + mSystemMemoryMap->Element[Counter].ElementSize), MEM_ADDR_SHFT_VAL);
      mAcpiParameter->MemoryBoardRange[NodeIndex] = MemoryBaseLimit;
    }
  }

  //
  // Mark all spare memory boards as 1 in MemSpareMask bitmap.  These are boards which are populated
  // but being held offline as a spare.
  //
  mAcpiParameter->MemSpareMask = mAcpiParameter->MemoryBoardBitMask ^ mIioUds->IioUdsPtr->SystemStatus.MemBoardPresent;

  mAcpiParameter->IioPresentBitMask = 0;
  mAcpiParameter->SocketBitMask = 0;
  mAcpiParameter->CpuSpareMask = mIioUds->IioUdsPtr->SystemStatus.CpuSpareMask;

  for (Counter = 0; Counter < MAX_SOCKET; Counter++) {
    if (!mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Counter].Valid) continue; 
    mAcpiParameter->SocketBitMask |= 1 << Counter;
    mAcpiParameter->IioPresentBitMask |= 1 << Counter;
  }

  mAcpiParameter->MmCfg = (UINT32)mIioUds->IioUdsPtr->PlatformData.PciExpressBase;

  //
  // Initialize TsegSize - 1MB aligned.
  //
  mAcpiParameter->TsegSize = (UINT32)(mIioUds->IioUdsPtr->PlatformData.MemTsegSize >> 20);
  PciHGPEAddr           = mIioUds->IioUdsPtr->PlatformData.PciExpressBase + 0x188;
  BusDevFunc            = 0x00;
  PcieHpBus             = 0;
  PcieHpDev             = 0;
  PcieHpFunc            = 0;
  //
  // Call AcpiPlatformHooks
  //  to fix up allowed S-states according
  //  to the power button mode, setup options,
  //  and platform type
  //
  // AptioV server override start: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.  
  /*
  mAcpiParameter->AcpiS3Enable  = (UINT8)FixupSystemSleepStates(3);
  mAcpiParameter->AcpiS4Enable  = (UINT8)FixupSystemSleepStates(4);
*/
  FixupSystemSleepStates();
  // AptioV server override end: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.
  
  Fixes = 0;
  //
  // Loop through the AML looking for values that we must fix up.
  //
  CurrPtr = (UINT8 *) TableHeader;
  for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {
    Signature = (UINT32 *) DsdtPointer;
      switch (*Signature) {
        //
        // DRHx, ATSx, RHSx are not in ASI files, so why is the code here?
        // Due to iASL compiler change and DSDT patch design change, if these items need support
        // then the ASI files will need to conform to the format requires for iASL to add the items
        // to the offset table, and grt.bat will need to filter them out when iASL is executed.
        //
        case 0x31485244 :   // "DRH1" - IIO1
          mAcpiParameter->DrhdAddr[0] = (UINTN) DsdtPointer;
          break;

        case 0x31535441 :   // "ATS1" - IIO1
          mAcpiParameter->AtsrAddr[0] = (UINTN)((UINT64 *) DsdtPointer + 4);
          break;

        case 0x31534852 :   // "RHS1" - IIO1
          mAcpiParameter->RhsaAddr[0] = (UINTN)((UINT64 *) DsdtPointer + 8);
          break;

        case 0x32485244 :   // "DRH2" - IIO2
          mAcpiParameter->DrhdAddr[1] = (UINTN) DsdtPointer;
          break;

        case 0x32535441 :   // "ATS2" - IIO2
          mAcpiParameter->AtsrAddr[1] = (UINTN)((UINT64 *) DsdtPointer + 4);
          break;

        case 0x32534852 :   // "RHS2" - IIO2
          mAcpiParameter->RhsaAddr[1] = (UINTN)((UINT64 *) DsdtPointer + 8);
          break;
          
          //AptioV server override start: Index number corrected for IIO3
        case 0x33485244 :   // "DRH3" - IIO3
          mAcpiParameter->DrhdAddr[2] = (UINTN) DsdtPointer;
          break;

        case 0x33535441 :   // "ATS3" - IIO3
          mAcpiParameter->AtsrAddr[2] = (UINTN)((UINT64 *) DsdtPointer + 4);
          break;

        case 0x33534852 :   // "RHS3" - IIO3
          mAcpiParameter->RhsaAddr[2] = (UINTN)((UINT64 *) DsdtPointer + 8);
          break;
          //AptioV server override end: Index number corrected for IIO3
          
        //
        // "FIX0" OperationRegion() in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '0')):
          * (UINT32 *) DsdtPointer = (UINT32) (UINTN) mAcpiParameter;
          Fixes++;
          break;

        //
        // "FIXT" OperationRegion() in Acpi\AcpiTables\Dsdt\PcieHp.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'T')):

         if((PcieHpDev == 0 && PcieHpFunc > 0) || (PcieHpFunc > 3)) {
             PcieHpDev++; 
             PcieHpFunc = 0;
          }
          if(PcieHpDev == 1 && PcieHpFunc > 1) { // Brickland doesn;t have IOU2 Dev 1 so we don;t need to skip it. 
             PcieHpDev++;
             PcieHpFunc = 0;
          }
           
          DEBUG((DEBUG_ERROR,"hpDev = %x, HpFunc= %x\n",PcieHpDev,PcieHpFunc));          
          if(PcieHpDev > 3) {
              if(MAX_SOCKET <= IioBusIndex) {
                 DEBUG ((EFI_D_ERROR, "Asserting the PatchDsdtTable- IioBusIndex  Index Bufferflow  :%d    %d ",IioBusIndex,BusDevFunc ));
                 ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER);
              }

            IioBusIndex++;
            PcieHpBus = mIioUds->IioUdsPtr->PlatformData.IIO_resource[IioBusIndex].BusBase;
            PcieHpDev = 0;
            PcieHpFunc = 0;
            PciHGPEAddr &= ~(0xFFFF000);    // clear bus device func numbers
          }
            
          BusDevFunc = (PcieHpBus << 8) | (PcieHpDev << 3) | PcieHpFunc;
          * (UINT32 *) DsdtPointer = (UINT32) (UINTN) (PciHGPEAddr + (BusDevFunc << 12));

          PcieHpFunc++;
          Fixes++;
          break;

        //
        // "FIXL" _BBN for IIO 0 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'L')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Iio[0];
          Fixes++;
          break;

        //
        // "FIXM" _BBN for IIO 1 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'M')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Iio[1];
          Fixes++;
          break;

        //
        // "FIXN" _BBN for IIO 2 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'N')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Iio[2];
          Fixes++;
          break;

        //
        // "FIXO" _BBN for IIO 3 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'O')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Iio[3];
          Fixes++;
          break;

        //
        // "FIXP" _BBN for Uncore 0 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'P')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Uncore[0];
          Fixes++;
          break;

        //
        // "FIXQ" _BBN for Uncore 1 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'Q')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Uncore[1];
          Fixes++;
          break;

        //
        // "FIXR" _BBN for Uncore 2 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'R')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Uncore[2];
          Fixes++;
          break;

        //
        // "FIXS" _BBN for Uncore 3 in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'S')):
          * (UINT32 *) (DsdtPointer) = 0;
          * (UINT32 *) (DsdtPointer) = (UINT8)BusBase_Uncore[3];
          Fixes++;
          break;

        //
        // "FIX1" BUS resource for Uncore 0 in Acpi\AcpiTables\Dsdt\Uncore.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '1')):
          * (UINT16 *) DsdtPointer      = 0;
          *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Uncore[0];
          *((UINT16 *) DsdtPointer + 2) = (UINT16)BusBase_Uncore[0];
          *((UINT16 *) DsdtPointer + 4) = 1;
          Fixes++;
          break;          

        //
        // "FIX2" BUS resource for Uncore 1 in Acpi\AcpiTables\Dsdt\Uncore.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '2')):
          * (UINT16 *) DsdtPointer      = 0;
           *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Uncore[1];
          *((UINT16 *) DsdtPointer + 2) = (UINT16)BusBase_Uncore[1];
          *((UINT16 *) DsdtPointer + 4) = 1;
          Fixes++;
          break;           

        //
        // "FIX3" BUS resource for Uncore 2 in Acpi\AcpiTables\Dsdt\Uncore.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '3')):
          * (UINT16 *) DsdtPointer      = 0;
          *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Uncore[2];
          *((UINT16 *) DsdtPointer + 2) = (UINT16)BusBase_Uncore[2];
          *((UINT16 *) DsdtPointer + 4) = 1;
          Fixes++;
          break;    

        //
        // "FIX4" BUS resource for Uncore 3 in Acpi\AcpiTables\Dsdt\Uncore.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '4')):
          * (UINT16 *) DsdtPointer      = 0;
          *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Uncore[3];
          *((UINT16 *) DsdtPointer + 2) = (UINT16)BusBase_Uncore[3];
          *((UINT16 *) DsdtPointer + 4) = 1;
          Fixes++;
          break;    

        //
        // "FIX5" BUS resource for IIO 0 in Acpi\AcpiTables\Dsdt\SysBus.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '5')):
          * (UINT16 *) DsdtPointer      = 0;
          if (BusLimit_Iio[0] > BusBase_Iio[0]) {
            *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Iio[0];
            *((UINT16 *) DsdtPointer + 2) = (UINT16)BusLimit_Iio[0];
            *((UINT16 *) DsdtPointer + 4) = (UINT16)(BusLimit_Iio[0] - BusBase_Iio[0] + 1);
          }
          Fixes++;
          break;          

        //
        // "FIX6" IO resource for IIO 0 in Acpi\AcpiTables\Dsdt\SysBus.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '6')):
        	            * (UINT16 *) DsdtPointer = 0;
        	            if (IoLimit_Iio[0] > IoBase_Iio[0]) {
        	                *((UINT16 *) DsdtPointer + 1) = IoBase_Iio[0];
        	                *((UINT16 *) DsdtPointer + 2) = IoLimit_Iio[0];
        	                *((UINT16 *) DsdtPointer + 4) = IoLimit_Iio[0] - IoBase_Iio[0] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIX9" BUS resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio1.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '9')):
        	            * (UINT16 *) DsdtPointer      = 0;
        	            if (BusLimit_Iio[1] > BusBase_Iio[1]) {
        	            *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Iio[1];
        	            *((UINT16 *) DsdtPointer + 2) = (UINT16)BusLimit_Iio[1];
        	            *((UINT16 *) DsdtPointer + 4) = (UINT16)(BusLimit_Iio[1] - BusBase_Iio[1] + 1);
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXA" IO resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio1.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'A')):
        	            * (UINT16 *) DsdtPointer = 0;
        	            if (IoLimit_Iio[1] > IoBase_Iio[1]) {
        	                *((UINT16 *) DsdtPointer + 1) = IoBase_Iio[1];
        	                *((UINT16 *) DsdtPointer + 2) = IoLimit_Iio[1];
        	                *((UINT16 *) DsdtPointer + 4) = IoLimit_Iio[1] - IoBase_Iio[1] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXD" BUS resource for IIO 2 in Acpi\AcpiTables\Dsdt\Iio2.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'D')):
        	            * (UINT16 *) DsdtPointer      = 0;
        	            if (BusLimit_Iio[2] > BusBase_Iio[2]) {
        	            *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Iio[2];
        	            *((UINT16 *) DsdtPointer + 2) = (UINT16)BusLimit_Iio[2];
        	            *((UINT16 *) DsdtPointer + 4) = (UINT16)(BusLimit_Iio[2] - BusBase_Iio[2] + 1);
        	            }
        	            Fixes++;
        	            break;


        //
        // "FIXE" IO resource for IIO 2 in Acpi\AcpiTables\Dsdt\Iio2.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'E')):
        	            * (UINT16 *) DsdtPointer = 0;
        	            if (IoLimit_Iio[2] > IoBase_Iio[2]) {
        	                *((UINT16 *) DsdtPointer + 1) = IoBase_Iio[2];
        	                *((UINT16 *) DsdtPointer + 2) = IoLimit_Iio[2];
        	                *((UINT16 *) DsdtPointer + 4) = IoLimit_Iio[2] - IoBase_Iio[2] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXH" BUS resource for IIO 3 in Acpi\AcpiTables\Dsdt\Iio3.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'H')):
        	            * (UINT16 *) DsdtPointer      = 0;
        	            if (BusLimit_Iio[3] > BusBase_Iio[3]) {
        	            *((UINT16 *) DsdtPointer + 1) = (UINT16)BusBase_Iio[3];
        	            *((UINT16 *) DsdtPointer + 2) = (UINT16)BusLimit_Iio[3];
        	            *((UINT16 *) DsdtPointer + 4) = (UINT16)(BusLimit_Iio[3] - BusBase_Iio[3] + 1);
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXI" IO resource for IIO 3 in Acpi\AcpiTables\Dsdt\Iio3.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'I')):
        	            * (UINT16 *) DsdtPointer = 0;
        	            if (IoLimit_Iio[3] > IoBase_Iio[3]) {
        	                *((UINT16 *) DsdtPointer + 1) = IoBase_Iio[3];
        	                *((UINT16 *) DsdtPointer + 2) = IoLimit_Iio[3];
        	                *((UINT16 *) DsdtPointer + 4) = IoLimit_Iio[3] - IoBase_Iio[3] + 1;
        	            }
        	            Fixes++;
        	            break;

		//
        // "FIXW" IO resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio1.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'W')):
          * (UINT16 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 1) {
            *((UINT16 *) DsdtPointer + 1)= (UINT16) 0x03b0;
            *((UINT16 *) DsdtPointer + 2) = (UINT16) 0x03bb;
            *((UINT16 *) DsdtPointer + 4) = (UINT16) 0x000C;
          }
          Fixes++;
          break;

		//
        // "FIXX" IO resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio1.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'X')):
          * (UINT16 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 1) {
            *((UINT16 *) DsdtPointer + 1) = (UINT16) 0x03c0;
            *((UINT16 *) DsdtPointer + 2) = (UINT16) 0x03df;
            *((UINT16 *) DsdtPointer + 4) = (UINT16) 0x0020;
          }
          Fixes++;
          break;

        //
        // "FIYB" IO resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio2.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'Y', 'B')):
          * (UINT16 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 2) {
            *((UINT16 *) DsdtPointer + 1) = (UINT16) 0x03b0;
            *((UINT16 *) DsdtPointer + 2) = (UINT16) 0x03bb;
            *((UINT16 *) DsdtPointer + 4) = (UINT16) 0x000C;
          }
          Fixes++;
          break;

        //
        // "FIYC" IO resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio2.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'Y', 'C')):
          * (UINT16 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 2) {
            *((UINT16 *) DsdtPointer + 1) = (UINT16) 0x03c0;
            *((UINT16 *) DsdtPointer + 2) = (UINT16) 0x03df;
            *((UINT16 *) DsdtPointer + 4) = (UINT16) 0x0020;
          }
          Fixes++;
          break;

        //
        // "FIYE" IO resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio3.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'Y', 'E')):
          * (UINT16 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 3) {
            *((UINT16 *) DsdtPointer + 1) = (UINT16) 0x03b0;
            *((UINT16 *) DsdtPointer + 2) = (UINT16) 0x03bb;
            *((UINT16 *) DsdtPointer + 4) = (UINT16) 0x000C;
          }
          Fixes++;
          break;

        //
        // "FIYF" IO resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio3.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'Y', 'F')):
          * (UINT16 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 3) {
            *((UINT16 *) DsdtPointer + 1) = (UINT16) 0x03c0;
            *((UINT16 *) DsdtPointer + 2) = (UINT16) 0x03df;
            *((UINT16 *) DsdtPointer + 4) = (UINT16) 0x0020;
          }
          Fixes++;
          break;
		  		  
        //
        // "FIX7" PCI32 resource for IIO 0 in Acpi\AcpiTables\Dsdt\SysBus.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '7')):
        	            * (UINT32 *) DsdtPointer      = 0;
        	            if (MemLimit32_Iio[0] > MemBase32_Iio[0]) {
        	                *((UINT32 *) DsdtPointer + 1) = MemBase32_Iio[0];
        	                *((UINT32 *) DsdtPointer + 2) = MemLimit32_Iio[0];
        	                *((UINT32 *) DsdtPointer + 4) = MemLimit32_Iio[0] - MemBase32_Iio[0] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXB" PCI32 resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio1.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'B')):
        	            * (UINT32 *) DsdtPointer = 0;
        	            if (MemLimit32_Iio[1] > MemBase32_Iio[1]) {
        	                *((UINT32 *) DsdtPointer + 1) = MemBase32_Iio[1];
        	                *((UINT32 *) DsdtPointer + 2) = MemLimit32_Iio[1];
        	                *((UINT32 *) DsdtPointer + 4) = MemLimit32_Iio[1] - MemBase32_Iio[1] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXF" PCI32 resource for IIO 2 in Acpi\AcpiTables\Dsdt\Iio2.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'F')):
        	            * (UINT32 *) DsdtPointer = 0;
        	            if (MemLimit32_Iio[2] > MemBase32_Iio[2]) {
        	                *((UINT32 *) DsdtPointer + 1) = MemBase32_Iio[2];
        	                *((UINT32 *) DsdtPointer + 2) = MemLimit32_Iio[2];
        	                *((UINT32 *) DsdtPointer + 4) = MemLimit32_Iio[2] - MemBase32_Iio[2] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXJ" PCI32 resource for IIO 3 in Acpi\AcpiTables\Dsdt\Iio3.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'J')):
        	            * (UINT32 *) DsdtPointer = 0;
        	            if (MemLimit32_Iio[3] > MemBase32_Iio[3]) {
        	                *((UINT32 *) DsdtPointer + 1) = MemBase32_Iio[3];
        	                *((UINT32 *) DsdtPointer + 2) = MemLimit32_Iio[3];
        	                *((UINT32 *) DsdtPointer + 4) = MemLimit32_Iio[3] - MemBase32_Iio[3] + 1;
        	            }
        	            Fixes++;
        	            break;

		//
        // "FIXU" Video resource for IIO 0 in Acpi\AcpiTables\Dsdt\SysBus.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'U')):
          * (UINT32 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 0) {
        	*((UINT32 *) DsdtPointer + 1) = 0x000a0000;
        	*((UINT32 *) DsdtPointer + 2) = 0x000bffff;
        	*((UINT32 *) DsdtPointer + 4) = 0x00020000;
          }
          Fixes++;
          break;

        //
        // "FIXV" Video resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio1.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'V')):
          * (UINT32 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 1) {
            *((UINT32 *) DsdtPointer + 1) = 0x000a0000;
            *((UINT32 *) DsdtPointer + 2) = 0x000bffff;
            *((UINT32 *) DsdtPointer + 4) = 0x00020000;
          }
          Fixes++;
          break;

        //
        // "FIYA" Video resource for IIO 2 in Acpi\AcpiTables\Dsdt\Iio2.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'Y', 'A')):
          * (UINT32 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 2) {
            *((UINT32 *) DsdtPointer + 1) = 0x000a0000;
            *((UINT32 *) DsdtPointer + 2) = 0x000bffff;
            *((UINT32 *) DsdtPointer + 4) = 0x00020000;
          }
          Fixes++;
          break;

        //
        // "FIYF" Video resource for IIO 3 in Acpi\AcpiTables\Dsdt\Iio3.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'Y', 'D')):
          * (UINT32 *) DsdtPointer = 0;
          if (mSystemConfiguration.LegacyVgaSoc == 3) {
            *((UINT32 *) DsdtPointer + 1) = 0x000a0000;
        	*((UINT32 *) DsdtPointer + 2) = 0x000bffff;
        	*((UINT32 *) DsdtPointer + 4) = 0x00020000;					
          }
          Fixes++;
          break;
          
        //
        // "FIX8" PCI64 resource for IIO 0 in Acpi\AcpiTables\Dsdt\SysBus.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', '8')):
        	            * (UINT64 *) DsdtPointer = 0;
        	            if (MemLimit64_Iio[0] > MemBase64_Iio[0]) {
        	                *((UINT64 *) DsdtPointer + 1) = (UINT64) MemBase64_Iio[0];
        	                *((UINT64 *) DsdtPointer + 2) = (UINT64) MemLimit64_Iio[0];
        	                *((UINT64 *) DsdtPointer + 4) = (UINT64) MemLimit64_Iio[0] - (UINT64) MemBase64_Iio[0] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXC" PCI64 resource for IIO 1 in Acpi\AcpiTables\Dsdt\Iio1.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'C')):
        	            * (UINT64 *) DsdtPointer = 0;
        	            if (MemLimit64_Iio[1] > MemBase64_Iio[1]) {
        	                *((UINT64 *) DsdtPointer + 1) = (UINT64) MemBase64_Iio[1];
        	                *((UINT64 *) DsdtPointer + 2) = (UINT64) MemLimit64_Iio[1];
        	                *((UINT64 *) DsdtPointer + 4) = (UINT64) MemLimit64_Iio[1] - (UINT64) MemBase64_Iio[1] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXG" PCI64 resource for IIO 2 in Acpi\AcpiTables\Dsdt\Iio2.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'G')):
        	            * (UINT64 *) DsdtPointer = 0;
        	            if (MemLimit64_Iio[2] > MemBase64_Iio[2]) {
        	                *((UINT64 *) DsdtPointer + 1) = (UINT64) MemBase64_Iio[2];
        	                *((UINT64 *) DsdtPointer + 2) = (UINT64) MemLimit64_Iio[2];
        	                *((UINT64 *) DsdtPointer + 4) = (UINT64) MemLimit64_Iio[2] - (UINT64) MemBase64_Iio[2] + 1;
        	            }
        	            Fixes++;
        	            break;

        //
        // "FIXK" PCI64 resource for IIO 3 in Acpi\AcpiTables\Dsdt\Iio3.asi
        //
        case (SIGNATURE_32 ('F', 'I', 'X', 'K')):
        	            * (UINT64 *) DsdtPointer = 0;
        	            if (MemLimit64_Iio[3] > MemBase64_Iio[3]) {
        	                *((UINT64 *) DsdtPointer + 1) = (UINT64) MemBase64_Iio[3];
        	                *((UINT64 *) DsdtPointer + 2) = (UINT64) MemLimit64_Iio[3];
        	                *((UINT64 *) DsdtPointer + 4) = (UINT64) MemLimit64_Iio[3] - (UINT64) MemBase64_Iio[3] + 1;
        	            }
        	            Fixes++;
        	            break;
        	            
        default:
          break;
      }
  }


  CurrPtr = (UINT8 *) TableHeader;

  for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {

       //fix CpuMemHp.asi "%" value = 0x25, force no same ASL code string as it...
       if ((DsdtPointer[0] == 'C') && (DsdtPointer[1] == 'P')  && (DsdtPointer[4] == 0x25)) {

         if (mCpuOrderSorted) {
           CpuCount = CpuCount + 1;
           DEBUG((EFI_D_ERROR, ":: Skt[%x]  CP%c%c  %02x%04x\n", CpuSkt, DsdtPointer[2],DsdtPointer[3], DsdtPointer[4], (UINT16)DsdtPointer[5]));

           CpuSkt = DsdtPointer[6];
           CpuIndex = DsdtPointer[5];
           CpuIndex = mCpuIndexTable[CpuIndex] & 0xFF;

           if ((CpuIndex == 0xFF) || (mAcpiParameter->ProcessorBitMask[CpuSkt] == 0)) {
             DsdtPointer[4] = (UINT8) 0xFF;
           } else {
             DsdtPointer[4] = (UINT8) ((CpuSkt << mNumOfBitShift) + CpuIndex);
           }

           //Update IO Address
           (UINT16) *(UINT16 *) (DsdtPointer+5) = 0x410;
           DEBUG((EFI_D_ERROR, "::: --- Update: Skt[%x]  CP%c%c  %02x%04x\n", CpuSkt, DsdtPointer[2],DsdtPointer[3], DsdtPointer[4], (UINT16)DsdtPointer[5]));
         }
       }

       //
       // Find APTC name
       //
       if((DsdtPointer[0] == 'A') && (DsdtPointer[1] == 'P') && (DsdtPointer[2] == 'T') && (DsdtPointer[3] == 'C')) {
          NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (DsdtPointer);
          if (NamePtr->StartByte != AML_NAME_OP) {
               DEBUG(( EFI_D_ERROR, "...Found 'APTC', but it is not NAME_OP, continue...\n "));
            continue;
          }


           Counter = DsdtPointer[7];
           DEBUG(( EFI_D_ERROR, "\n::ACPI::  Found 'APTC'...Counter = DsdtPointer[7] = %x\n\n", Counter));
           for (i = 0; i < Counter; i++) {
             CpuIndex = i + 8;
             DEBUG(( EFI_D_ERROR, "Before override, DsdtPointer[%x] = %x,   ", CpuIndex, DsdtPointer[CpuIndex] ));
             DsdtPointer[CpuIndex] = (UINT8) mCpuIndexTable[i];
             DEBUG(( EFI_D_ERROR, "Then override value = %x \n", DsdtPointer[CpuIndex] ));
           }
         }
// AptioV server override start: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.
/*       

    //
    // Fix up _S3
    //
    if ((DsdtPointer[0] == '_') && (DsdtPointer[1] == 'S') && (DsdtPointer[2] == '3')) {
      NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (DsdtPointer);
      if (NamePtr->StartByte != AML_NAME_OP) {
        DEBUG(( EFI_D_ERROR, "...Found '_S3', but it is not NAME_OP, continue...\n "));
        continue;
      }
      
      if (!mAcpiParameter->AcpiS3Enable) {
        //
        // S3 disabled
        //
        DsdtPointer[0] = 'D';
      }
    }

    //
    // Fix up _S4
    //
    if ((DsdtPointer[0] == '_') && (DsdtPointer[1] == 'S') && (DsdtPointer[2] == '4')) {
      NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (DsdtPointer);
      if (NamePtr->StartByte != AML_NAME_OP) {
        DEBUG(( EFI_D_ERROR, "...Found '_S4', but it is not NAME_OP, continue...\n "));
        continue;
      }
      
      if (!mAcpiParameter->AcpiS4Enable) {
        //
        // S4 disabled
        //
        DsdtPointer[0] = 'D';
      }
    } */       
    // AptioV server override end: AMI ACPI driver updates sleep states object based on setup controls from ACPI configuration.
  }

  //return Status;
  return EFI_SUCCESS;

}

EFI_STATUS
PatchSRATableAllApicIds (
  IN OUT   EFI_ACPI_STATIC_RESOURCE_AFFINITY_TABLE  *SRAAcpiTable
  )
/*++

  Routine Description: 

    Update the SRAT APIC IDs.

  Arguments:              

    *SRAAcpiTable   - The table to be set

  Returns:                

    EFI_SUCCESS -  Returns Success

--*/
{
  UINT8                       CpuThreadIndex;
  UINT8                       *ApicTablePtr;
  UINT8                       *ProxDomainPtr;

  UINT8                       ApicIds[EFI_ACPI_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT] = {
                                0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,
                                0x20, 0x22,

                                0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E,
                                0x60, 0x62,

                                0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9A, 0x9C, 0x9E,
                                0xA0, 0xA2,

                                0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
                                0xE0, 0xE2,

                                0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F,
                                0x21, 0x23,

                                0x41, 0x43, 0x45, 0x47, 0x49, 0x4B, 0x4D, 0x4F, 0x51, 0x53, 0x55, 0x57, 0x59, 0x5B, 0x5D, 0x5F,
                                0x61, 0x63,

                                0x81, 0x83, 0x85, 0x87, 0x89, 0x8B, 0x8D, 0x8F, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9B, 0x9D, 0x9F,
                                0xA1, 0xA3,

                                0xC1, 0xC3, 0xC5, 0xC7, 0xC9, 0xCB, 0xCD, 0xCF, 0xD1, 0xD3, 0xD5, 0xD7, 0xD9, 0xDB, 0xDD, 0xDF,
                                0xE1, 0xE3,
                              };

  UINT8                       ProxDomain[EFI_ACPI_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT] = {
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00,

                                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                                0x01, 0x01,

                                0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
                                0x02, 0x02,

                                0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                                0x03, 0x03,

                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00,

                                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                                0x01, 0x01,

                                0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
                                0x02, 0x02,

                                0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                                0x03, 0x03,
                              };

  ApicTablePtr = ApicIds;
  ProxDomainPtr = ProxDomain;

  for (CpuThreadIndex = 0; CpuThreadIndex < EFI_ACPI_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT; CpuThreadIndex++) {
  
    SRAAcpiTable->Apic[CpuThreadIndex].ApicId = *(ApicTablePtr + CpuThreadIndex);
    SRAAcpiTable->Apic[CpuThreadIndex].ProximityDomain = *(ProxDomainPtr + CpuThreadIndex);

    if (*(ApicTablePtr + CpuThreadIndex) != 0xff) {
      SRAAcpiTable->Apic[CpuThreadIndex].Flags = EFI_ACPI_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED;
    }

  }
  return EFI_SUCCESS;
}

EFI_STATUS
PatchMsctAcpiTable (
  IN OUT   EFI_ACPI_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE *MsctAcpiTable
  )
/*++

  Routine Description:

    Update the MSCT ACPI table

  Arguments:

    *MsctAcpiTable - The table to be set

  Returns:

    EFI_SUCCESS -  Returns Success

--*/
{
  UINTN             idx;
  UINT8             checksum;

  // Update Maximum Physical Address
  // NHM-EX has 44 address lines, so Maximum Physical Address is 2^44 - 1.
  MsctAcpiTable->MaxPhysicalAddress = (LShiftU64 (0x01, 44) - 1);

  // First Proximity Domain Information Structure reports characteristics for all proximity domains,
  // since the characteristics are the same for all proximity domains.
  MsctAcpiTable->ProxDomInfoStructure[0].ProxDomRangeLow  = 0;
  MsctAcpiTable->ProxDomInfoStructure[0].ProxDomRangeHigh = MsctAcpiTable->MaxNumProxDom;

  // Max Number of Threads that the processor can have
  MsctAcpiTable->ProxDomInfoStructure[0].MaxProcessorCapacity = (MAX_THREAD * MAX_CORE);

  // Max Memory capacity per proximity domain
  MsctAcpiTable->ProxDomInfoStructure[0].MaxMemoryCapacity = MsctAcpiTable->MaxPhysicalAddress; // 2 TB

  // Update Checksum
  MsctAcpiTable->Header.Checksum = 0;
  checksum = 0;
  for(idx = 0; idx < sizeof(EFI_ACPI_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE); idx++) {
    checksum = checksum + (UINT8) (((UINT8 *)(MsctAcpiTable))[idx]);
  }
  MsctAcpiTable->Header.Checksum = (UINT8) (0 - checksum);

  return EFI_SUCCESS;
}


#ifdef BDAT_SUPPORT
static
INT16 Crc16 (char *ptr, int count)
{
  INT16 crc, i;
  crc = 0;
  while (--count >= 0)
  {
    crc = crc ^ (INT16)(int)*ptr++ << 8;
    for (i = 0; i < 8; ++i)
    {
      if (crc & 0x8000)
      {
        crc = crc << 1 ^ 0x1021;
      }
      else
      {
        crc = crc << 1;
      }
    }
  }
  return (crc & 0xFFFF);
}

/**

    Update the BDAT ACPI table: Multiple instances of the BDAT DATA HOB are placed into one contiguos memory range

    @param *TableHeader   - The table to be set

    @retval EFI_SUCCESS -  Returns Success

**/
EFI_STATUS
PatchBdatAcpiTable (
  IN OUT   EFI_BDAT_ACPI_DESCRIPTION_TABLE *BdatAcpiTable
  )
/*++

  Routine Description:

    Update the BDAT ACPI table: Multiple instances of the BDAT DATA HOB are placed into one contiguos memory range

  Arguments:

    *TableHeader   - The table to be set

  Returns:

    EFI_SUCCESS -  Returns Success

--*/
{
  EFI_STATUS                    Status = EFI_SUCCESS;
  EFI_PHYSICAL_ADDRESS          Address, *AddressPointer;
  UINTN                         idx;
  UINTN                         CurrentHobSize;
  UINTN                         RemainingHobSizeMemSchema, RemainingHobSizeRmtSchema;
  EFI_HOB_GUID_TYPE             *GuidHob      = NULL;
  VOID                          *HobData      = NULL;
  UINT8                         checksum;
  EFI_TIME                      EfiTime;
  BDAT_STRUCTURE                *bdatHeaderStructPtr;
  UINT32                        *SchemasAddressLocationArray;
  UINT8                         socket;
  UINTN                         totalBDATstructureSize = 0;
  UINT16                        NumberExtraSchemas;
  UINT32                        BdatStructureSize;
#ifdef SSA_FLAG
  EFI_GUID                      gEfiMemoryMapDataHobBdatBssaGuid  = {0};
  UINT16                        NumberBssaSchemas = 0;
  UINT32                        GuidIdx;
  UINT32                        HobIdx;
  UINT32                        CurrentSchema;
  UINT32                        PreviousSchemaSize;
  UINT32                        RemainingHobSizeBssaSchema;
  BDAT_SCHEMA_HEADER_STRUCTURE  *bssaSchemaHeaderPtr;
#endif //SSA_FLAG

  Address = 0xffffffff;
  NumberExtraSchemas = 1;
#ifdef SSA_FLAG
  DEBUG ((EFI_D_ERROR, "PatchBdatAcpiTable Started\n"));
  for (GuidIdx = 0; GuidIdx < mSystemMemoryMap->bssaNumberDistinctGuids; GuidIdx++) {
    NumberBssaSchemas += mSystemMemoryMap->bssaNumberHobs[GuidIdx];  //No. of HOBS per GUID added up for all GUIDs created from calls to saveToBdat()
    DEBUG ((EFI_D_ERROR, "GuidIdx = %d, total num hobs: %d\n", GuidIdx,  mSystemMemoryMap->bssaNumberHobs[GuidIdx]));
  }

  RemainingHobSizeBssaSchema = mSystemMemoryMap->bssaBdatSize + (NumberBssaSchemas*sizeof(BDAT_SCHEMA_HEADER_STRUCTURE)); //Total size of all HOBs created by SaveToBdat() + NumberBssaSchemas*headerPerSchema
  NumberExtraSchemas += NumberBssaSchemas; //total HOBs sizes added up
  DEBUG ((EFI_D_ERROR, "NumberBssaSchemas = %d, total schema size: %d\n", NumberBssaSchemas,  RemainingHobSizeBssaSchema));
#endif //SSA_FLAG
  BdatStructureSize = sizeof(BDAT_STRUCTURE) + (NumberExtraSchemas * sizeof(UINT32));


#ifdef SSA_FLAG
  totalBDATstructureSize = BdatStructureSize + sizeof (BDAT_MEMORY_DATA_STRUCTURE) + sizeof (BDAT_RMT_STRUCTURE) + RemainingHobSizeBssaSchema;
#else
  totalBDATstructureSize = BdatStructureSize + sizeof (BDAT_MEMORY_DATA_STRUCTURE) + sizeof (BDAT_RMT_STRUCTURE);
#endif //SSA_FLAG
  DEBUG ((EFI_D_ERROR, "Total BDAT size: %d\n", totalBDATstructureSize));

//Allocating RealTime Memory for BDAT. A block large enough to copy both structs + BSSA Bdat; so that they are "contiguos".
  Status  = gBS->AllocatePages (
                   AllocateMaxAddress,
                   EfiACPIMemoryNVS,
                   EFI_SIZE_TO_PAGES (totalBDATstructureSize),
                   &Address
                   );

  if (EFI_ERROR (Status)) {
    return Status;
  }

  bdatHeaderStructPtr = (BDAT_STRUCTURE *)Address;
  AddressPointer = (EFI_PHYSICAL_ADDRESS *)Address;

  ZeroMem ((VOID *)AddressPointer, totalBDATstructureSize); // The memory location where the HOB's are to be copied to

  //
  // Create BIOS Data Signature
  //
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[0] = 'B';
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[1] = 'D';
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[2] = 'A';
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[3] = 'T';
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[4] = 'H';
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[5] = 'E';
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[6] = 'A';
  bdatHeaderStructPtr->BdatHeader.BiosDataSignature[7] = 'D';
  //
  // Structure size
  //
  bdatHeaderStructPtr->BdatHeader.BiosDataStructSize = (UINT32) totalBDATstructureSize;
  //
  // Primary Version
  //
  bdatHeaderStructPtr->BdatHeader.PrimaryVersion =  BDAT_PRIMARY_VER;
  //
  // Secondary Version
  //
  bdatHeaderStructPtr->BdatHeader.SecondaryVersion =  BDAT_SECONDARY_VER;
  //
  // CRC16 value of the BDAT_STRUCTURE
  //
  bdatHeaderStructPtr->BdatHeader.Crc16 = Crc16 ((char *)bdatHeaderStructPtr, BdatStructureSize);//Check if this CRC is OK
  bdatHeaderStructPtr->BdatSchemas.SchemaListLength = 1 + NumberExtraSchemas;
  bdatHeaderStructPtr->BdatSchemas.Reserved = 0;
  bdatHeaderStructPtr->BdatSchemas.Reserved1 = 0;
  //Initialize the Time parameters in the SCHEMA_LIST_STRUCTURE
  Status = gRT->GetTime (&EfiTime, NULL);
  if (!EFI_ERROR (Status)) {
    bdatHeaderStructPtr->BdatSchemas.Year =   EfiTime.Year;
    bdatHeaderStructPtr->BdatSchemas.Month =  EfiTime.Month;
    bdatHeaderStructPtr->BdatSchemas.Day =    EfiTime.Day;
    bdatHeaderStructPtr->BdatSchemas.Hour =   EfiTime.Hour;
    bdatHeaderStructPtr->BdatSchemas.Minute = EfiTime.Minute;
    bdatHeaderStructPtr->BdatSchemas.Second = EfiTime.Second;
  }

  //Saving the "Schema Offsets" from the BDAT base in RT Memory into the Schemas Array in BDAT_STRUCT"; AddressPointer -> Base Address of RT Memory Allocated
  SchemasAddressLocationArray = bdatHeaderStructPtr->BdatSchemas.Schemas; //Schemas - array name
  SchemasAddressLocationArray[0] = BdatStructureSize;  //*(x+1)=x[1]. Offset of BDAT_STRUCTURE start from BDAT base                                      //Offset of BDAT_STRUCTURE start from BDAT base
  SchemasAddressLocationArray[1] = SchemasAddressLocationArray[0] + sizeof(BDAT_MEMORY_DATA_STRUCTURE);  //Offset of BDAT_MEMORY_DATA_STRUCTURE start from BDAT base
  //For the next Schema, Offset would be = baseAddress of BDAT_STRUCTURE + sizeof(BDAT_STRUCTURE) + sizeof(BDAT_MEMORY_DATA_STRUCTURE for Schema1)

  //
  // Update BDAT ACPI table
  //
  BdatAcpiTable->BdatGas.Address = (UINT64)Address;
  DEBUG ((EFI_D_ERROR, "BdatRegionAddress = %x\n", (UINT64)Address));

  //Copy BDAT base address to ScratchPad5
  for(socket = 0; socket < MAX_SOCKET; socket++) {
    if(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[socket].Valid) {
      mCpuCsrAccess->WriteCpuCsr(socket, 0, BIOSNONSTICKYSCRATCHPAD5_UBOX_MISC_REG, (UINT32)Address);
    }
  }

  //
  // Copy Bdat structure from HostGenerator to Reserved memory
  //

  RemainingHobSizeMemSchema = sizeof(BDAT_MEMORY_DATA_STRUCTURE);
  RemainingHobSizeRmtSchema = sizeof(BDAT_RMT_STRUCTURE);

  //
  // Get first BDAT Memory Data HOB
  //
  GuidHob = GetFirstGuidHob (&gEfiMemoryMapDataHobBdatGuid);  //GuidHob -> The first HOB instance of the matched GUID

  //We first copy the BDAT_STRUCT into RunTime Memory; then move the AddressPointer to the end of BDAT_STRUCT; to start Copying the Memory Schema from the HOB
  Address = Address + BdatStructureSize; //Incrementing ACPI Memory address by CurrentHobSize size to maintain contiguos memory for all instances of the HOB
  //DEBUG ((EFI_D_ERROR, "Bdat address after BDAT_STRUCTURE = %x\n", (UINT64)Address));

  AddressPointer = (EFI_PHYSICAL_ADDRESS *)Address;
#ifdef SSA_FLAG
  HobIdx = 0;
#endif

  DEBUG ((EFI_D_ERROR, "Remaining HobSize MemSchema: %d\n", RemainingHobSizeMemSchema));
  while (RemainingHobSizeMemSchema) {
    HobData = GET_GUID_HOB_DATA (GuidHob);  //HobData-> A pointer to the Base address of the data buffer in a HOB
    CurrentHobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);  //Size of that matched instance of the  Data HOB.. HOB 0/1/2
//Prinitng out schemaID and size the 1st times; later calls - ID
#ifdef SSA_FLAG
    if (HobIdx == 0) {
      bssaSchemaHeaderPtr = (BDAT_SCHEMA_HEADER_STRUCTURE *)HobData;
      DEBUG ((EFI_D_ERROR, "Getting schema %g. Size: %d\n", &(bssaSchemaHeaderPtr->SchemaId), bssaSchemaHeaderPtr->DataSize));
    } else {
      DEBUG ((EFI_D_ERROR, "Getting hob: %d\n", HobIdx));
    }
    HobIdx++;
#endif
    //
    // Trim the HOB data padding so there is no overflow on the buffer
    //
    if (CurrentHobSize > RemainingHobSizeMemSchema){
      CurrentHobSize = RemainingHobSizeMemSchema;
    }

    if (CurrentHobSize < MAX_HOB_ENTRY_SIZE){
      RemainingHobSizeMemSchema = 0;
    } else {
      RemainingHobSizeMemSchema -= CurrentHobSize;
    }

    //
    // Get next BDAT data hob, if none left, results NULL
    //
    GuidHob = GET_NEXT_HOB (GuidHob); // Increment to next HOB
    GuidHob = GetNextGuidHob (&gEfiMemoryMapDataHobBdatGuid, GuidHob);  // Now search for next instance of the BDAT HOB

    //Copy Bdat structure from HOB's to Reserved memory
    CopyMem ((VOID *)AddressPointer, (VOID *)HobData, CurrentHobSize);

    Address = Address + CurrentHobSize; //Incrementing ACPI Memory address by CurrentHobSize size to maintain contiguos memory for all instances of the HOB
    AddressPointer = (EFI_PHYSICAL_ADDRESS *)Address;
  } //while loop

  //
  // Get first BDAT RMT Data HOB
  //
  GuidHob = GetFirstGuidHob (&gEfiRmtDataHobBdatGuid);
#ifdef SSA_FLAG
  HobIdx = 0;
#endif
  DEBUG ((EFI_D_ERROR, "Remaining HobSize RmtSchema: %d\n", RemainingHobSizeRmtSchema));
  while (RemainingHobSizeRmtSchema) {
    HobData = GET_GUID_HOB_DATA (GuidHob);
    CurrentHobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
#ifdef SSA_FLAG
    if (HobIdx == 0) {
      bssaSchemaHeaderPtr = (BDAT_SCHEMA_HEADER_STRUCTURE *)HobData;
      DEBUG ((EFI_D_ERROR, "Getting schema %g. Size: %d\n", &(bssaSchemaHeaderPtr->SchemaId), bssaSchemaHeaderPtr->DataSize));
    } else {
      DEBUG ((EFI_D_ERROR, "Getting hob: %d\n", HobIdx));
    }
    HobIdx++;
#endif
    //
    // Trim the HOB data padding so there is no overflow on the buffer
    //
    if (CurrentHobSize > RemainingHobSizeRmtSchema){
      CurrentHobSize = RemainingHobSizeRmtSchema;
    }

    if (CurrentHobSize < MAX_HOB_ENTRY_SIZE){
      RemainingHobSizeRmtSchema = 0;
    } else {
      RemainingHobSizeRmtSchema -= CurrentHobSize;
    }

    //
    // Get next BDAT data hob, if none left, results NULL
    //
    GuidHob = GET_NEXT_HOB (GuidHob);
    GuidHob = GetNextGuidHob (&gEfiRmtDataHobBdatGuid, GuidHob);

    CopyMem ((VOID *)AddressPointer, (VOID *)HobData, CurrentHobSize);

    Address = Address + CurrentHobSize;
    AddressPointer = (EFI_PHYSICAL_ADDRESS *)Address;
  } //while loop

#ifdef SSA_FLAG
  //
  //Saving to RT Memory BDAT Data received from HOBs generated due to call/calls to SaveToBdat()
  //
  PreviousSchemaSize = sizeof(BDAT_RMT_STRUCTURE);
  CurrentSchema = 2;
  for (GuidIdx = 0; GuidIdx < mSystemMemoryMap->bssaNumberDistinctGuids; GuidIdx++) {
    gEfiMemoryMapDataHobBdatBssaGuid  = mSystemMemoryMap->bssaBdatGuid[GuidIdx]; //get first GUID instance
    GuidHob = GetFirstGuidHob (&gEfiMemoryMapDataHobBdatBssaGuid);
    DEBUG ((EFI_D_ERROR, "Getting BIOS SSA result with GUID  %g\n", &gEfiMemoryMapDataHobBdatBssaGuid));
    for (HobIdx = 0; HobIdx < mSystemMemoryMap->bssaNumberHobs[GuidIdx]; HobIdx++) { //looping through all HOBs linked to that GUID
      HobData = GET_GUID_HOB_DATA (GuidHob);
      CurrentHobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
      DEBUG ((EFI_D_ERROR, "Initial HOB size  %d; remaining HOB size %d\n", CurrentHobSize, RemainingHobSizeBssaSchema));
      //Setting the header first
      if (RemainingHobSizeBssaSchema < sizeof(BDAT_SCHEMA_HEADER_STRUCTURE)) {
        //Nothing we can do, break execution
        DEBUG ((EFI_D_ERROR, "Not enough space to add schema header to BIOS SSA result\n"));
        RemainingHobSizeBssaSchema = 0;
        break;
      }
      //Each HOB has a header added to it (BDAT_SCHEMA_HEADER_STRUCTURE)
      bssaSchemaHeaderPtr = (BDAT_SCHEMA_HEADER_STRUCTURE *)Address;
      bssaSchemaHeaderPtr->SchemaId = gEfiMemoryMapDataHobBdatBssaGuid;
      RemainingHobSizeBssaSchema -= sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
      Address = Address + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
      AddressPointer = (EFI_PHYSICAL_ADDRESS *)Address;
      //CRC16 value of the BDAT_SCHEMA_HEADER_STRUCTURE
      bssaSchemaHeaderPtr->Crc16 = Crc16 ((char *)bssaSchemaHeaderPtr, sizeof(BDAT_SCHEMA_HEADER_STRUCTURE));

      GuidHob = GET_NEXT_HOB (GuidHob); // Increment to next HOB
      GuidHob = GetNextGuidHob (&gEfiMemoryMapDataHobBdatBssaGuid, GuidHob);  // Now search for next instance of the BDAT HOB

      SchemasAddressLocationArray[CurrentSchema] = SchemasAddressLocationArray[CurrentSchema - 1] + PreviousSchemaSize;
      CurrentSchema++;

      if (RemainingHobSizeBssaSchema < CurrentHobSize) {
        DEBUG ((EFI_D_ERROR, "Not enough space to add complete BIOS SSA result\n"));
        CurrentHobSize = RemainingHobSizeBssaSchema;
      }
      //HOB size won't overflow a UINT32.
      bssaSchemaHeaderPtr->DataSize = (UINT32)CurrentHobSize + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
      DEBUG ((EFI_D_ERROR, "Setting schema %g size to %d\n", &(bssaSchemaHeaderPtr->SchemaId), bssaSchemaHeaderPtr->DataSize));
      //HOB size won't overflow a UINT32.
      PreviousSchemaSize = (UINT32)CurrentHobSize + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
      DEBUG ((EFI_D_ERROR, "Copying %d bytes to 0x%x\n", CurrentHobSize, AddressPointer));

     //Copy HOB to RT Memory
      CopyMem ((VOID *)AddressPointer, (VOID *)HobData, (UINT32)CurrentHobSize);
      //HOB size won't overflow a UINT32.
      DEBUG ((EFI_D_ERROR, "HOB size  %d; remaining HOB size %d\n", CurrentHobSize, RemainingHobSizeBssaSchema));
      RemainingHobSizeBssaSchema -= (UINT32)CurrentHobSize;
      Address = Address + CurrentHobSize; //Incrementing ACPI Memory address by CurrentHobSize size to maintain contiguos memory for all instances of the HOB
      AddressPointer = (EFI_PHYSICAL_ADDRESS *)Address;
      if (RemainingHobSizeBssaSchema == 0) {
        break;
      }
    }
    if (RemainingHobSizeBssaSchema == 0) {
      break;
    }
  }
#endif //SSA_FLAG

  //
  // Update checksum
  //
  BdatAcpiTable->Header.Checksum = 0;
  checksum = 0;
  for(idx = 0; idx < sizeof(EFI_BDAT_ACPI_DESCRIPTION_TABLE); idx++) {
    checksum = checksum + (UINT8) (((UINT8 *)(BdatAcpiTable))[idx]);
  }
  BdatAcpiTable->Header.Checksum = (UINT8) (0 - checksum);

  return Status;
}
#endif


EFI_STATUS
MpstActionEntryUpdate(
  IN OUT EFI_ACPI_MEMORY_POWER_STATE_TABLE *MpstTable
  )
{
  EFI_STATUS                          Status = EFI_SUCCESS;
  //EFI_ACPI_MPST_ACTION_ITEM         *Action;
  //EFI_ACPI_MPST_MAILBOX           *Mailbox;

  //
  // Allocate ACPI Reserved Memory for the MPST Mail Box.
  //
  Status = gBS->AllocatePool (EfiReservedMemoryType, sizeof (EFI_ACPI_MPST_MAILBOX), (VOID **) &mMpstSupport.MpstMailbox);
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "MPST: MPST aborted as Mailbox cannot be allocated.\n"));
    return EFI_ABORTED;
  }
  ZeroMem ((VOID *)&mMpstSupport.MpstMailbox, sizeof(EFI_ACPI_MPST_MAILBOX));

  //
  // Patch action items entries in the MPST Table
  //
  /*  Action = MpstTable->actionEntryList;
  Mailbox = mMpstSupport.MpstMailbox;

  Action[EFI_ACPI_SET_MEMORY_POWER_STATE].Register.Address    = (UINT64) &(Mailbox->Command);

  Action[EFI_ACPI_GET_MEMORY_POWER_STATE].Register.Address    = (UINT64) &(Mailbox->Command);

  Action[EFI_ACPI_REQUESTED_POWER_STATE_ID].Register.Address  = (UINT64) &(Mailbox->PowerState);

  Action[EFI_ACPI_CURRENT_POWER_STATE_ID].Register.Address    = (UINT64) &(Mailbox->PowerState); // used Command structure to avoid bit-field issues 

  Action[EFI_ACPI_MEMORY_POWER_NODE_ID].Register.Address      = (UINT64) &(Mailbox->MemoryPowerNodeId);
  Action[EFI_ACPI_MEMORY_POWER_NODE_ID].Register.RegisterBitWidth = 16;  // PowerNodeId field in Mailbox is 16-bits side
  Action[EFI_ACPI_MEMORY_POWER_NODE_ID].Register.AccessSize   = 2;  // PowerNodeId field in Mailbox is 16-bits

  Action[EFI_ACPI_CHECK_BUSY_STATUS].Register.Address         = (UINT64) &(Mailbox->Response); // used Command structure to avoid bit-field issues 

  Action[EFI_ACPI_GET_COMMAND_STATUS].Register.Address        = (UINT64) &(Mailbox->Response); // used Command structure to avoid bit-field issues 
  */
  return Status;
}


VOID
DebugDisplayMpst(
  IN OUT EFI_ACPI_MEMORY_POWER_STATE_TABLE *MpstTable
  )
{
  UINT8    Node;
  UINT8    PwrState;
  UINT8    PwrStateInfo;
  //UINT8    Action;
  UINT8    Dimm;

  DEBUG((EFI_D_ERROR, "\n<ACPI MPST Table after Patching>\n"));
  // Print out the action entry list
  DEBUG((EFI_D_ERROR, "PCC Identifier = %02x\n", MpstTable->Header.MpstPccIdentifier));
  DEBUG((EFI_D_ERROR, "MemPwrNodeCnt  = %04x\n", MpstTable->MemPwrNodeCnt));

  for (Node = 0; Node < mMemoryPowerNodeStrucId + 1; Node++) {
    DEBUG((EFI_D_ERROR, "  MemoryPowerNodeId : %02x", Node));
    DEBUG((EFI_D_ERROR, "  MemoryPowerNodeStrucId: %02x", mMpstSupport.MemPwrNodeInfo[Node].MemoryPowerNode));
    DEBUG((EFI_D_ERROR, "  Node: %02x", mMpstSupport.MemPwrNodeInfo[Node].Node));
    DEBUG((EFI_D_ERROR, "  ChId: %02x", mMpstSupport.MemPwrNodeInfo[Node].Ch));
    DEBUG((EFI_D_ERROR, "  PowerNodeFlag: %02x", mMpstSupport.MemPwrNodeInfo[Node].PowerManagedFlag));
    DEBUG((EFI_D_ERROR, "  Tad: %02x \n", mMpstSupport.MemPwrNodeInfo[Node].Tad));
  }

  DEBUG((EFI_D_ERROR, "\n"));

  for (Node = 0; Node < mMemoryPowerNodeStrucId +1; Node++) {
    DEBUG((EFI_D_ERROR, "MemoryPowerNode[%d]\n", Node));
    DEBUG((EFI_D_ERROR, "  PowerNodeFlag              = %02x\n", MpstTable->MemoryPowerNode[Node].PowerManagedFlag));
    DEBUG((EFI_D_ERROR, "  MemoryPowerNodeId          = %04x\n", MpstTable->MemoryPowerNode[Node].MemoryPowerNodeId));
    DEBUG((EFI_D_ERROR, "  ACPI Table Length          = %08x\n", MpstTable->MemoryPowerNode[Node].Length));
    DEBUG((EFI_D_ERROR, "  AddressBase                = %08x%08x\n", MpstTable->MemoryPowerNode[Node].AddressBaseHigh, MpstTable->MemoryPowerNode[Node].AddressBaseLow));
    DEBUG((EFI_D_ERROR, "  Length                     = %08x%08x\n", MpstTable->MemoryPowerNode[Node].LengthHigh, MpstTable->MemoryPowerNode[Node].LengthLow));
    DEBUG((EFI_D_ERROR, "  NumberOfPowerStates        = %02x\n", MpstTable->MemoryPowerNode[Node].NumberOfPowerStates));
    DEBUG((EFI_D_ERROR, "  NumberOfPhysicalComponents = %02x\n", MpstTable->MemoryPowerNode[Node].NumberOfPhysicalComponents));
    for (PwrState=0; PwrState<EFI_ACPI_MEMORY_POWER_STATES_COUNT; PwrState++) {
      DEBUG((EFI_D_ERROR, "  PowerState[%d]\n", PwrState));
      DEBUG((EFI_D_ERROR, "    PowerStateValue     = %02x\n", MpstTable->MemoryPowerNode[Node].PowerState[PwrState].PowerStateValue));
      DEBUG((EFI_D_ERROR, "    PowerStateInfoIndex = %02x\n", MpstTable->MemoryPowerNode[Node].PowerState[PwrState].PowerStateInfoIndex));
    }
    for (Dimm=0; Dimm<MAX_DIMM; Dimm++) {
      DEBUG((EFI_D_ERROR, "  Physical Component Identifier[%d] = %02x\n", Dimm, MpstTable->MemoryPowerNode[Node].PhysicalComponent[Dimm]));
    }
    DEBUG((EFI_D_ERROR, "\n"));
  }
  DEBUG((EFI_D_ERROR, "\nPwrStateInfoCnt = %04x\n", MpstTable->PwrStateInfoCnt));

   for (PwrStateInfo=0; PwrStateInfo< mMemoryPowerNodeStrucId +1 ; PwrStateInfo++) {
     for (PwrState=0; PwrState<EFI_ACPI_MEMORY_POWER_STATES_COUNT; PwrState++) {
       DEBUG((EFI_D_ERROR, "PowerStateInfo[%d], PwrState[%d]\n", PwrStateInfo, PwrState));
       DEBUG((EFI_D_ERROR, "  PowerStateStructureID = %02d\n", MpstTable->PowerStateInfo[PwrStateInfo][PwrState].PowerStateStructureID));
       DEBUG((EFI_D_ERROR, "  Flag                  = %04d\n", MpstTable->PowerStateInfo[PwrStateInfo][PwrState].Flag));
       DEBUG((EFI_D_ERROR, "  AveragePowerConsumed  = %08d\n", MpstTable->PowerStateInfo[PwrStateInfo][PwrState].AveragePowerConsumed));
       DEBUG((EFI_D_ERROR, "  PowerSaving           = %08d\n", MpstTable->PowerStateInfo[PwrStateInfo][PwrState].PowerSaving));
       DEBUG((EFI_D_ERROR, "  ExitLatencyToMps0     = %ld\n", MpstTable->PowerStateInfo[PwrStateInfo][PwrState].ExitLatencyToMps0));
       //DEBUG((EFI_D_ERROR, "  ExitLatencyToPrevMps  = %lX\n\n", MpstTable->PowerStateInfo[PwrStateInfo][PwrState].ExitLatencyToPrevMps));
     }
  }
  DEBUG((EFI_D_ERROR, "\n</ACPI MPST Table after Patching>\n"));
}

VOID
GetPowervalue(
  UINT8  WTDimmType,
  UINT8  WTLvAndDramDensity,
  UINT8  WTSpdByte7,
  UINT8  WTFrequency,
  UINT8  WTDimmPos
)
{
  UINT16 i = 0;
  UINT16 EntryCount;
  UINT32 ckePwr =00;
  UINT32 AvgPwr =00;
  UINT32 srPwr = 00;

  EntryCount = (sizeof (DimmWT)) / (sizeof (struct DimmWTRowEntryStruct));

  for (i = 0; i < EntryCount; i ++) {
    if((DimmWT[i].WTDimmType == WTDimmType) && (DimmWT[i].WTSpdByte7 == WTSpdByte7) 
        && (DimmWT[i].WTLvAndDramDensity == WTLvAndDramDensity)
        && (DimmWT[i].WTFrequency == WTFrequency) && ((DimmWT[i].WTDimmPos == WTDimmPos)))  {
      ckePwr  = (DimmWT[i].DramMinPwrClosedPage + DimmWT[i].DramMinPwrOpenPage) / 2; // in w
      // AvgPwr = (DimmWT[i].DramMaxPwr - DimmWT[i].DramMinPwrPpdCkeFast )  / 2  + DimmWT[i].DramMinPwrPpdCkeFast
      //AvgPwr = (DimmWT[i].DramMaxPwr + DimmWT[i].DramMinPwrPpdCkeFast) * 500;  // in mw
      AvgPwr = (DimmWT[i].DramMaxPwr + ckePwr ) * 500;  // in mw
      srPwr = (ckePwr * 200) ; // in mw - 20% of cke pwr  ckePwr * (20/100) * 1000
      //DEBUG((EFI_D_ERROR,"    MemWeigh Entry(Dec): %02d,AvgPwr: %04ld, ckePwr: %04ld, srPwr: %04ld \n",i, AvgPwr, ckePwr, srPwr));
      mPowerConsumed[0] += AvgPwr;
      mPowerConsumed[1] += srPwr;
      break;
    }
  }
  return;
}

VOID
MpstUpdatePowerState(
  EFI_ACPI_MEMORY_POWER_STATE_TABLE   *MpstTable,
  UINT8                       node,
  UINT8                       tad,
  UINT8                       chId,
  UINT16                      MemoryPowerNodeId
  )
{
  UINT8 dimm,haCh,haNum;
  EFI_ACPI_MEMORY_POWER_NODE  *MemoryPowerNode;
  UINT8  WTDimmType;
  UINT8  WTLvAndDramDensity;
  UINT8  WTSpdByte7;
  UINT8  WTFrequency;
  UINT8  WTDimmPos;
  UINT32 m0PwrConsumed =0;
  UINT32 m1PwrConsumed =0;
  UINT64 PwrSaving =0;
  UINT8  Unsupported = 0xff; 

  MemoryPowerNode = &MpstTable->MemoryPowerNode[mMemoryPowerNodeStrucId];
  CopyMem(&MpstTable->PowerStateInfo[MemoryPowerNodeId][0], &MpstTable->PowerStateInfo[0][0], 2 * sizeof(EFI_ACPI_MEMORY_POWER_STATE_INFO));

  MpstTable->PowerStateInfo[MemoryPowerNodeId][0].AveragePowerConsumed = 00;
  MpstTable->PowerStateInfo[MemoryPowerNodeId][0].PowerSaving = 00;
  MpstTable->PowerStateInfo[MemoryPowerNodeId][1].AveragePowerConsumed = 00;
  MpstTable->PowerStateInfo[MemoryPowerNodeId][1].PowerSaving = 00;

  haNum   = 0;
  haCh    = chId;
  if(mSystemMemoryMap->NodeInfo[node].NumChPerHA == 2) { // 2 HA case.
    haNum   = NODE_TO_MC(node);
    if( (haNum == 1) && (chId >=2) ) haCh  = chId -2;
  }

  mPowerConsumed[0]= 00;
  mPowerConsumed[1]= 00;
  MemoryPowerNode->PowerManagedFlag = 00;
  WTFrequency = 00;

  switch (mSystemMemoryMap->NodeInfo[node].MemFreq) {
    case DDR_1867:
      WTFrequency = 4;
      break;

    case DDR_1600:
      WTFrequency = 3;
      break;

    case DDR_1333:
      WTFrequency = 2;
      break;

    case DDR_1067:
      WTFrequency = 1;
      break;

    case DDR_800:
      WTFrequency = 0;
      break;

    default:
      WTFrequency = Unsupported;
      break;
  }

  if(WTFrequency == Unsupported)  {
    DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR," \n MpstUpdatePowerState: MemFrequency not found in MemWeight Table - Node: %d, chId: %d, FreqNum: %d, \n", 
          node, chId, mSystemMemoryMap->NodeInfo[node].MemFreq));
    return;
  }

  for (dimm = 0; dimm < MAX_DIMM; dimm++) {
    MemoryPowerNode->PhysicalComponent[dimm]= 0xffff;
    if (mSystemMemoryMap->NodeInfo[node].ChannelInfo[haCh].DimmInfo[dimm].Present == 0) continue;

    MemoryPowerNode->PhysicalComponent[dimm]= dimm;
    //
    // Look up DIMM command weight value in the fixed table
    // First get the data needed to match a table entry for this dimm
    //
    WTDimmType = 00;
    WTDimmType = mSystemMemoryMap->NodeInfo[node].ChannelInfo[haCh].DimmInfo[dimm].actKeyByte2;
// AptioV Server Override Start: Used proper macros for Dimm Type
    if (!((mSystemMemoryMap->NodeInfo[node].DimmType == RDIMM) ||
          (mSystemMemoryMap->NodeInfo[node].DimmType == UDIMM) ||
          (mSystemMemoryMap->NodeInfo[node].DimmType == RDIMMandUDIMM))) {
// AptioV Server Override End: Used proper macros for Dimm Type
      DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR," \n MpstUpdatePowerState: Dimm Type Not found in MemWeight Table (skipping) - Node: %d, chId: %d, Dimm: %d, DimmType: %d, \n", 
            node, chId, dimm, mSystemMemoryMap->NodeInfo[node].DimmType));
      MemoryPowerNode->PowerManagedFlag = 00;
      mMpstSupport.MemPwrNodeInfo[MemoryPowerNodeId].DimmMap |= 1 << dimm;
      continue;
    }
    if ((WTDimmType == SPD_UDIMM) && (mSystemMemoryMap->NodeInfo[node].ChannelInfo[haCh].DimmInfo[dimm].SPDMemBusWidth & BIT3)) {
      WTDimmType |= 0x10;
    }

    WTSpdByte7 = 00;
    WTSpdByte7 = mSystemMemoryMap->NodeInfo[node].ChannelInfo[haCh].DimmInfo[dimm].actSPDModuleOrg;
  
    WTLvAndDramDensity = 0x00;
    WTLvAndDramDensity = mSystemMemoryMap->NodeInfo[node].ChannelInfo[haCh].DimmInfo[dimm].actSPDSDRAMBanks & 0x0F;
    if ((WTLvAndDramDensity < SPD_1Gb) || (WTLvAndDramDensity > SPD_4Gb)) {
      DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR," \n MpstUpdatePowerState: Unsupported Dram Dencity in MemWeight Table (skipping) - Node: %d, chId: %d, Dimm: %d, WTLvAndDramDensity: %d, \n", 
            node, chId, dimm, WTLvAndDramDensity));
      MemoryPowerNode->PowerManagedFlag = 00;
      mMpstSupport.MemPwrNodeInfo[MemoryPowerNodeId].DimmMap |= 1 << dimm;
      continue;
    }
    if (mSystemMemoryMap->NodeInfo[node].DdrVoltage & SPD_VDD_135) {
      WTLvAndDramDensity |= 0x10;
    }

    if (dimm == 2) {
      WTDimmPos = 1;
    } else {
      WTDimmPos = dimm;
    }

    //DEBUG((EFI_D_ERROR,"  DIMM Details : node: %x, ChId: %x, dimm : %x,",node, chId, dimm));
    //DEBUG((EFI_D_ERROR," WTDimmType: %x, WTLvAndDramDensity: %x,",WTDimmType, WTLvAndDramDensity));
    //DEBUG((EFI_D_ERROR," WTSpdByte7: %x,WTFrequency: %x \n",WTSpdByte7, WTFrequency));
    GetPowervalue(WTDimmType, WTLvAndDramDensity, WTSpdByte7, WTFrequency, WTDimmPos);  

    MemoryPowerNode->PowerManagedFlag |= FLAG_ENABLED;
    MemoryPowerNode->PowerManagedFlag |= FLAG_POWERMANAGED;
    mMpstSupport.MemoryPowerNodeStatus[mMemoryPowerNodeStrucId] = MPST_POWER_STATE_ACTIVE;
    mMpstSupport.MemPwrNodeInfo[MemoryPowerNodeId].DimmMap |= 1 << dimm;
  }

  m0PwrConsumed = mPowerConsumed[0];
  MpstTable->PowerStateInfo[MemoryPowerNodeId][0].AveragePowerConsumed = m0PwrConsumed;
  m1PwrConsumed = mPowerConsumed[1];
  MpstTable->PowerStateInfo[MemoryPowerNodeId][1].AveragePowerConsumed = m0PwrConsumed;

  MemoryPowerNode->PowerManagedFlag |= FLAG_ENABLED;
  MemoryPowerNode->PowerManagedFlag |= FLAG_POWERMANAGED;

  if(m0PwrConsumed && m1PwrConsumed)
    PwrSaving = (((UINT64)m0PwrConsumed - m1PwrConsumed)*100)/m0PwrConsumed;
  else  {
    PwrSaving = 00;
    DEBUG((EFI_D_ERROR," \n MpstUpdatePowerState: m0PwrConsumed or m1PwrConsumed is zero - Node: %d, tad: %d, chId: %d, Dimm: %d \n", 
           node, tad, chId, dimm));
  }

  MpstTable->PowerStateInfo[MemoryPowerNodeId][0].PowerSaving = 00;
  MpstTable->PowerStateInfo[MemoryPowerNodeId][1].PowerSaving = (UINT32)PwrSaving;
  MemoryPowerNode->PowerState[MPST_POWER_STATE_ACTIVE].PowerStateInfoIndex = (UINT8)(MemoryPowerNodeId * 2);
  MemoryPowerNode->PowerState[MPST_POWER_STATE_SR].PowerStateInfoIndex = (UINT8)( MemoryPowerNodeId * 2 ) + 1;
}
  
VOID
MpstPowerNodeAndPowerStateUpdate(
  EFI_ACPI_MEMORY_POWER_STATE_TABLE   *MpstTable
  )
{
  EFI_ACPI_MEMORY_POWER_NODE  *MemoryPowerNode;
  UINT8                       node, tad, chId, i;
  UINT64                      Base, Length, TadLimit;
  BOOLEAN                     SameChFound = FALSE;
  BOOLEAN                     PowerManaged = FALSE;
  BOOLEAN                     MemHoleFound = FALSE;
  NODE_CH_PWR_MEM_INFO        NodeChPwrMemInfo[MAX_MEM_NODE * TAD_RULES];  // NodeId/ChId relationship to MemoryNodeID.

  //
  // Copy MemoryPowerNode[0] in Mpst table to use as a template even before it is patched
  //
  CopyMem(&mMemoryPowerNodeTemplate, &MpstTable->MemoryPowerNode[00], sizeof(EFI_ACPI_MEMORY_POWER_NODE));

  mMemoryPowerNodeStrucId = 0;
  mMainMemoryPowerNodeId = 0;

  for (i = 0; i < EFI_ACPI_MEMORY_POWER_NODES_COUNT; i++) {
    MpstTable->MemoryPowerNode[i].Length = sizeof(EFI_ACPI_MEMORY_POWER_NODE);
  }

  for (node = 0; node < MAX_MEM_NODE; node++) {
    if (mSystemMemoryMap->NodeInfo[node].Enabled == 0) continue;

    for (tad = 0; tad < TAD_RULES; tad++) {
      //DEBUG((EFI_D_ERROR," Node = %d, tad = %x, tadEn = %d", node, tad, mSystemMemoryMap->NodeInfo[node].TAD[tad].Enable));
      //DEBUG((EFI_D_ERROR," Limit = %x left shift 26 \n",mSystemMemoryMap->NodeInfo[node].TAD[tad].Limit));
      if(mSystemMemoryMap->NodeInfo[node].TAD[tad].Enable == 00) continue;
      if(mMemoryPowerNodeStrucId >= EFI_ACPI_MEMORY_POWER_NODES_COUNT) {
        DEBUG(( EFI_D_ERROR, "AcpiPlatform: ERROR mMemoryPowerNodeStrucId=%d is greater then EFI_ACPI_MEMORY_POWER_NODES_COUNT=%d \n",
          mMemoryPowerNodeStrucId,EFI_ACPI_MEMORY_POWER_NODES_COUNT));
        return;
      }
      NodeChPwrMemInfo[mMemoryPowerNodeStrucId].ChId = 0xf;
      NodeChPwrMemInfo[mMemoryPowerNodeStrucId].NodeId = 0xf;

      chId = mSystemMemoryMap->NodeInfo[node].TADChnIndex[tad][0];
      // Copy the defaults from template node 
      MemoryPowerNode = &MpstTable->MemoryPowerNode[mMemoryPowerNodeStrucId];

      mMpstSupport.MemPwrNodeInfo[mMemoryPowerNodeStrucId].PowerManagedFlag = 00;
      mMpstSupport.MemPwrNodeInfo[mMemoryPowerNodeStrucId].Node = 00;
      mMpstSupport.MemPwrNodeInfo[mMemoryPowerNodeStrucId].Tad = 00;
      mMpstSupport.MemPwrNodeInfo[mMemoryPowerNodeStrucId].Ch = 00;

      CopyMem(MemoryPowerNode, &mMemoryPowerNodeTemplate, sizeof(EFI_ACPI_MEMORY_POWER_NODE));

      MemoryPowerNode->AddressBaseLow = mSystemMemoryMap->NodeInfo[node].TAD[tad].ChannelAddressLow;
      MemoryPowerNode->AddressBaseHigh = mSystemMemoryMap->NodeInfo[node].TAD[tad].ChannelAddressHigh;
      TadLimit = (UINT64)mSystemMemoryMap->NodeInfo[node].TAD[tad].Limit << 26; // Limit is in 64MB units
      // 4167995: Base Address for Memory Power node is to be in bytes not 64MB units.
      Base  = (((UINT64)MemoryPowerNode->AddressBaseHigh << 0x20) | MemoryPowerNode->AddressBaseLow) << 26;
      MemoryPowerNode->AddressBaseLow = Base & 0xFFFFFFFF;
      MemoryPowerNode->AddressBaseHigh = Base >> 0x20;
// AptioV Server Override End: Made changes for Memory Node Base Address and Length calculation.
      // Memory power node that falls below 4Gb make it as not power managed
      PowerManaged = TRUE;
      if(Base < 0x100000000) PowerManaged = FALSE;
// AptioV Server Override Start: MMIO range from 2GB-4GB is already considered in MRC while calculating TAD
      // Removing the 3gb-4gb memory and updating the entry for this range at the end.
/*      if(TadLimit == 0x100000000) {
        TadLimit  = 0xc0000000;
        MemHoleFound =TRUE;
      }
      if(Base == 0xc0000000) {
        Base  = 0x100000000;
        MemHoleFound =TRUE;
      }*/
// AptioV Server Override End: MMIO range from 2GB-4GB is already considered in MRC while calculating TAD
      Length = TadLimit - Base;
      MemoryPowerNode->LengthLow = Length & 0xffffffff;
      MemoryPowerNode->LengthHigh = Length >> 0x20;
      MemoryPowerNode->Length = sizeof(EFI_ACPI_MEMORY_POWER_NODE);
      SameChFound = FALSE;
      for (i = 0; i < mMemoryPowerNodeStrucId; i++) { 
        if((NodeChPwrMemInfo[i].ChId == chId) && (NodeChPwrMemInfo[i].NodeId == node)){ 
          SameChFound  = TRUE;
          MemoryPowerNode->MemoryPowerNodeId = NodeChPwrMemInfo[i].MemoryNodeId;
          break;
        }
      }
      if(SameChFound == FALSE) {
        NodeChPwrMemInfo[mMemoryPowerNodeStrucId].ChId = chId;
        NodeChPwrMemInfo[mMemoryPowerNodeStrucId].NodeId = node;
        NodeChPwrMemInfo[mMemoryPowerNodeStrucId].MemoryNodeId = mMainMemoryPowerNodeId;
        MemoryPowerNode->MemoryPowerNodeId = mMainMemoryPowerNodeId;
        mMainMemoryPowerNodeId++;
      }
      MpstUpdatePowerState(MpstTable, node, tad, chId, MemoryPowerNode->MemoryPowerNodeId);

      if( PowerManaged == FALSE) MemoryPowerNode->PowerManagedFlag &= ~(FLAG_POWERMANAGED);

      if( SameChFound == TRUE) {
        MemoryPowerNode->PowerManagedFlag = (UINT8) NodeChPwrMemInfo[i].PowerManagedFlag;
      }

      NodeChPwrMemInfo[mMemoryPowerNodeStrucId].ChId = chId;
      NodeChPwrMemInfo[mMemoryPowerNodeStrucId].NodeId = node;
      NodeChPwrMemInfo[mMemoryPowerNodeStrucId].MemoryNodeId = MemoryPowerNode->MemoryPowerNodeId;
      NodeChPwrMemInfo[mMemoryPowerNodeStrucId].PowerManagedFlag = MemoryPowerNode->PowerManagedFlag;
      mMpstSupport.MemPwrNodeInfo[MemoryPowerNode->MemoryPowerNodeId].PowerManagedFlag = MemoryPowerNode->PowerManagedFlag;
      mMpstSupport.MemPwrNodeInfo[MemoryPowerNode->MemoryPowerNodeId].Node = node;
      mMpstSupport.MemPwrNodeInfo[MemoryPowerNode->MemoryPowerNodeId].Tad = tad;
      mMpstSupport.MemPwrNodeInfo[MemoryPowerNode->MemoryPowerNodeId].Ch = chId;
      mMpstSupport.MemPwrNodeInfo[MemoryPowerNode->MemoryPowerNodeId].MemoryPowerNode = mMemoryPowerNodeStrucId;
      mPrevEnergyConsumed[mMemoryPowerNodeStrucId]  = 00;
      mPrevPcctEnergyValue[mMemoryPowerNodeStrucId] = 00;
      mOverflowCnt[mMemoryPowerNodeStrucId]         = 00;
      mAddOffset[mMemoryPowerNodeStrucId]           = 00;
      mSubOffset[mMemoryPowerNodeStrucId]           = 00;
      mMemoryPowerNodeStrucId++;
    }
  }
// AptioV Server Override Start: MMIO range from 2GB-4GB is already considered in MRC while calculating TAD
/*  if(MemHoleFound == TRUE) {
      DEBUG((EFI_D_ERROR, "MpstPowerNodeAndPowerStateUpdate 19 mMainMemoryPowerNodeId = %x \n", mMainMemoryPowerNodeId));
    MemoryPowerNode = &MpstTable->MemoryPowerNode[mMemoryPowerNodeStrucId];
    CopyMem(MemoryPowerNode, &mMemoryPowerNodeTemplate, sizeof(EFI_ACPI_MEMORY_POWER_NODE));
    mMpstSupport.MemPwrNodeInfo[mMainMemoryPowerNodeId].PowerManagedFlag = 00;
    MemoryPowerNode->MemoryPowerNodeId = mMainMemoryPowerNodeId;
    MemoryPowerNode->AddressBaseLow = (UINT32)mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
    MemoryPowerNode->AddressBaseHigh = 0;
    MemoryPowerNode->LengthLow = (UINT32)(0x100000000 - mIioUds->IioUdsPtr->PlatformData.PciExpressBase);
    MemoryPowerNode->LengthHigh = 00;
    MemoryPowerNode->PowerManagedFlag = 00;
    DEBUG((EFI_D_ERROR, "MpstPowerNodeAndPowerStateUpdate 20 AddressBaseLow = %x AddressBaseHigh = %x LengthLow = %x LengthHigh = %x\n", MemoryPowerNode->AddressBaseLow, MemoryPowerNode->AddressBaseHigh, MemoryPowerNode->LengthLow, MemoryPowerNode->LengthHigh));
    mMainMemoryPowerNodeId++; 
    mMemoryPowerNodeStrucId++;
  }
*/
// AptioV Server Override End: MMIO range from 2GB-4GB is already considered in MRC while calculating TAD
  mMpstSupport.MaxPwrNode = mMainMemoryPowerNodeId;
}

EFI_STATUS
PatchMemoryPowerStateTable (
  IN OUT EFI_ACPI_MEMORY_POWER_STATE_TABLE *MpstTable
  )
{
  EFI_HANDLE                        Handle;
  EFI_STATUS                        Status;

  ZeroMem ((VOID *)&mMpstSupport, sizeof (EFI_MPST_SUPPORT_PROTOCOL));
  mMpstSupport.MpstTable = MpstTable;

  //
  // Update Action Entry in MPST Table
  // 
  MpstActionEntryUpdate(MpstTable);
 
  //
  // Update Power Node and power state
  //
  MpstPowerNodeAndPowerStateUpdate(MpstTable);

  //
  // Display MPST Data
  //
  //DebugDisplayMpst(MpstTable);

  //
  // Install protocol
  //
  Handle = NULL;
  Status = gBS->InstallProtocolInterface (&Handle, &gEfiMpstSupportProtocolGuid, EFI_NATIVE_INTERFACE, &mMpstSupport);
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "MPST: MPST Support Protocol cannot be installed.\n"));
    return EFI_ABORTED;
  }

  //
  // All power states supported are hardware autonomous
  // 
  return  EFI_SUCCESS;
}

EFI_STATUS
PatchPlatformMemoryTopologyTable (
  IN OUT EFI_ACPI_PLATFORM_MEMORY_TOPOLOGY_TABLE *PmttTable
  )
{
// AptioV Server Override Start: Changes done for PMTT Table - Structures present for only if dimms are populated.
  UINT8                                   DimmNum = 0, ch, dimm, Socket, Mc;
  EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC        *TopLevelmemAggrDevStruc;
  EFI_ACPI_MEM_CTRL_STRUC                 *MemCtrlStruc;
  EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC *PhyCompIdentStruc;
  EFI_STATUS                              Status = EFI_SUCCESS;
  BOOLEAN                                 SmBiosProtocolFound = FALSE;
  SMBIOS_TABLE_TYPE17                     *SmbiosType17Record;
  EFI_SMBIOS_HANDLE                       SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
  EFI_SMBIOS_PROTOCOL                     *mSmbios;
  EFI_SMBIOS_TYPE                         SmbiosType;
  EFI_SMBIOS_TABLE_HEADER                 *SmbiosRecord;

  DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"\n <PMTT ACPI TABLE> \n"));
  DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"\n  mPmttAcpiTable Addr:  %lx \n", PmttTable));

  Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &mSmbios);
  if (!(EFI_ERROR(Status))) {
    SmBiosProtocolFound = TRUE;
  }
  //
  // Update PMTT main Header 
  //
  PmttTable->Header.Length = sizeof (EFI_ACPI_PLATFORM_MEMORY_TOPOLOGY_TABLE) - (MAX_SOCKET * sizeof (EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC));
  for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
	  if ((mSystemMemoryMap->NodeInfo[SKTMC_TO_NODE(Socket, 0)].Enabled == 0) && (mSystemMemoryMap->NodeInfo[SKTMC_TO_NODE(Socket, 1)].Enabled == 0)) continue;

    TopLevelmemAggrDevStruc = (EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC *)((UINTN)(PmttTable) + PmttTable->Header.Length);
    DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"  TopLevelmemAggrDevStruc (Socket)-  Socket: %x, Addr:  %lx \n", Socket, TopLevelmemAggrDevStruc)); 
  
    TopLevelmemAggrDevStruc->Type     = EFI_ACPI_TOP_LEVEL_MEMORY_TYPE_SOCKET;
    TopLevelmemAggrDevStruc->Rsvd     = 00;
    TopLevelmemAggrDevStruc->Flag     = EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_TLAD | EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_PHYELEMENT | EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_VOLATILE ;
    TopLevelmemAggrDevStruc->Rsvd1    = 00; 
    TopLevelmemAggrDevStruc->Length   = sizeof (EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC) - (NUM_MEM_CONTROLLERS * sizeof (EFI_ACPI_MEM_CTRL_STRUC));
    PmttTable->Header.Length          += TopLevelmemAggrDevStruc->Length;
    TopLevelmemAggrDevStruc->SckIdent = Socket;
    TopLevelmemAggrDevStruc->Rsvd2    = 00;
  
    DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"    Type: %x, Flag: %x, SckIdent: %x, \n", TopLevelmemAggrDevStruc->Type,TopLevelmemAggrDevStruc->Flag,TopLevelmemAggrDevStruc->SckIdent));
  
    for (Mc = 0; Mc < MAX_HA; Mc++) {
            if (mSystemMemoryMap->NodeInfo[SKTMC_TO_NODE(Socket, Mc)].Enabled == 0) continue;
    // EFI_ACPI_MEM_CTRL_STRUC  
    	    MemCtrlStruc              = (EFI_ACPI_MEM_CTRL_STRUC *)((UINTN)(TopLevelmemAggrDevStruc) + TopLevelmemAggrDevStruc->Length);
	    DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"    Memory Controller Structure-  Addr:  %lx\n", MemCtrlStruc)); 

    MemCtrlStruc->Type        = EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_TLAD;
    MemCtrlStruc->Rsvd        = 00;
	    MemCtrlStruc->Length = sizeof (EFI_ACPI_MEM_CTRL_STRUC) - (MAX_CH * MAX_DIMM * sizeof (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC)) - ((MAX_SOCKET -1) * sizeof (UINT32));
    MemCtrlStruc->Flag        = EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_TLAD | EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_PHYELEMENT | EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_VOLATILE ;
    MemCtrlStruc->Rsvd1       = 00;
	    MemCtrlStruc->Rsvd2 = 00;
    PmttTable->Header.Length += MemCtrlStruc->Length;

    // EFI_ACPI_MEMCTRL_CHAR_TABLE - TBD
    MemCtrlStruc->MemCtrlCharTable.ReadLatency         = MPST_TBI;
    MemCtrlStruc->MemCtrlCharTable.WriteLatency        = MPST_TBI;
    MemCtrlStruc->MemCtrlCharTable.ReadBW              = MPST_TBI;
    MemCtrlStruc->MemCtrlCharTable.WriteBW             = MPST_TBI;
    MemCtrlStruc->MemCtrlCharTable.OptimalAccUnit      = MPST_TBI;
    MemCtrlStruc->MemCtrlCharTable.OptimalAccAlignment = MPST_TBI;

	    MemCtrlStruc->NumProxDomains  = PROXMITY_DOMAIN_INFO_PRESENT;
 
    if(MemCtrlStruc->NumProxDomains  != PROXMITY_DOMAIN_INFO_NOT_PRSENT) {
      // To be implemented.
	      MemCtrlStruc->ProxDomain[0]  = Socket;
      //MemCtrlStruc->NumPhyComponents  = 00;
    }
    DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"      Type: %x, Flag: %x, Number of ProxmityDomains: %x, \n", MemCtrlStruc->Type,MemCtrlStruc->Flag,MemCtrlStruc->NumProxDomains));

     // EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC
	    //PhyCompIdentStruc = (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC *)((UINTN)(MemCtrlStruc) + sizeof (EFI_ACPI_MEM_CTRL_STRUC));

    for (ch = 0; ch < MAX_CH; ch++) {
	      if (mSystemMemoryMap->NodeInfo[SKTMC_TO_NODE(Socket, Mc)].ChannelInfo[ch].Enabled == 0) continue;
      for (dimm = 0; dimm < MAX_DIMM; dimm++) {
		if (mSystemMemoryMap->NodeInfo[SKTMC_TO_NODE(Socket, Mc)].ChannelInfo[ch].DimmInfo[dimm].Present == 0) continue;
		PhyCompIdentStruc = (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC *)((UINTN)(MemCtrlStruc) + MemCtrlStruc->Length);
        DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"      Physical Components Identifier Structure-  Addr:  %lx, Size: %x \n", PhyCompIdentStruc, sizeof (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC))); 

        //PhyCompIdentStruc->Length += sizeof (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC);
        PhyCompIdentStruc->Type   = PHYSICAL_COMPONENT_IDENTIFIER_TYPE_DIMM;
        PhyCompIdentStruc->Rsvd   = 00;
		PhyCompIdentStruc->Flag   = EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_TLAD | EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_PHYELEMENT | EFI_ACPI_TOP_LEVEL_SKT_MEM_STRUC_VOLATILE;
        PhyCompIdentStruc->Rsvd1  = 00;
        PhyCompIdentStruc->Length = sizeof (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC);
        PmttTable->Header.Length += PhyCompIdentStruc->Length;
        //DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"\n  mPmttAcpiTable Length:  %lx \n", PmttTable->Header.Length));
		PhyCompIdentStruc->PhyCompIdentifier = DimmNum;
        PhyCompIdentStruc->Rsvd2   = 00;
		PhyCompIdentStruc->Size = (mSystemMemoryMap->NodeInfo[SKTMC_TO_NODE(Socket, Mc)].ChannelInfo[ch].DimmInfo[dimm].DimmSize) << 6; // Dimm Capacity in GB. Memsize is in MB.
		PhyCompIdentStruc->SmBiosHandle = SMBIOS_HANDLE_INVALID;  
        if (SmBiosProtocolFound == TRUE) {
		  //SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
          SmbiosType = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
		  while (1) {
          Status = mSmbios->GetNext (mSmbios, &SmbiosHandle, &SmbiosType, &SmbiosRecord, NULL);
          if (!(EFI_ERROR(Status))) {
            SmbiosType17Record = (SMBIOS_TABLE_TYPE17 *) SmbiosRecord;
		      if (SmbiosType17Record->Size != 0) {
		        ASSERT (SmbiosType17Record->Size == PhyCompIdentStruc->Size); 
			    PhyCompIdentStruc->SmBiosHandle = SmbiosType17Record->Hdr.Handle;
			    break;
          }
        }
		    else {
			    break;
		    }
		  }
		}
        DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"        Type: %x, Flag: %x, Number of ProxmityDomains: %x \n", PhyCompIdentStruc->Type,PhyCompIdentStruc->Flag,MemCtrlStruc->NumProxDomains));
		DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"        PhyCompIdentifier: %x, DimmSize: %x MB,\n", PhyCompIdentStruc->PhyCompIdentifier,PhyCompIdentStruc->Size));
 
        MemCtrlStruc->Length += (UINT16)PhyCompIdentStruc->Length;
        DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"      MemCtrlStruc->Length: %x, \n", MemCtrlStruc->Length));

        PhyCompIdentStruc = (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC *)((UINTN)(PhyCompIdentStruc) + (sizeof (EFI_ACPI_PHYSICAL_COMP_IDENTIFIER_STRUC)) );
		DimmNum++;
      }
    }

    TopLevelmemAggrDevStruc->Length += (UINT16)MemCtrlStruc->Length;
    DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"    TopLevelmemAggrDevStruc Final Length: %x\n\n",  TopLevelmemAggrDevStruc->Length));
    }
//    NodeNum++;
  }
// AptioV Server Override End: Changes done for PMTT Table - Structures present for only if dimms are populated.
  DEBUG((EFI_D_LOAD|EFI_D_INFO|EFI_D_ERROR,"  mPmttAcpiTable Final Length:  %lx \n", PmttTable->Header.Length));

  return Status;
}

EFI_STATUS
PatchPlatformCommunicationsChannelTable(
  EFI_ACPI_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE   *PcctTable
  )
{
  EFI_STATUS                               Status;
  EFI_ACPI_PCC_SHARED_MEMORY_REGION_MPST   *LocalSharedMemRegion;
  //UINT8                                  *CommunicationSpace;

  //
  // Allocate ACPI Reserved Memory for the MPST Mail Box.
  //

  if( mSystemConfiguration.Mpst ) {
    Status = gBS->AllocatePool (EfiReservedMemoryType, sizeof (EFI_ACPI_PCC_SHARED_MEMORY_REGION_MPST), (VOID **) &mMpstSupport.SharedMemRegion);
    if (EFI_ERROR(Status)) {
      DEBUG((EFI_D_ERROR, "MPST: MPST aborted as Mailbox cannot be allocated.\n"));
      return EFI_ABORTED;
    }
    ZeroMem ((VOID *)mMpstSupport.SharedMemRegion, sizeof(EFI_ACPI_PCC_SHARED_MEMORY_REGION_MPST));

    LocalSharedMemRegion            = (EFI_ACPI_PCC_SHARED_MEMORY_REGION_MPST *)(UINTN)(mMpstSupport.SharedMemRegion);
    LocalSharedMemRegion->Signature = EFI_ACPI_3_0_PCC_MPST_SIGNATURE;
    LocalSharedMemRegion->Command.Data   = 00;
    LocalSharedMemRegion->Status.Data    = 00;

    // CommunicationSpace  = (UINT8 *)((UINTN)(mPcctSupport->SharedMemRegion) + sizeof(EFI_ACPI_PCC_SHARED_MEMORY_REGION_MPST));
    PcctTable->PccSubspaceStructure[PCC_SBSTANCE_MPST_ENTRY].BaseAddress  = (UINT64)(UINTN)(mMpstSupport.SharedMemRegion);
    PcctTable->PccSubspaceStructure[PCC_SBSTANCE_MPST_ENTRY].MemLength    = sizeof(EFI_ACPI_PCC_SHARED_MEMORY_REGION_MPST);
  }
  return EFI_SUCCESS;
}

VOID
DebugDisplayReOrderTable(
  VOID
  )
{
  UINT32 Index;

  DEBUG ((EFI_D_ERROR, "Index  AcpiProcId  ApicId  Flags  SwApicId  Skt\n"));
  for (Index=0; Index<MAX_CPU_NUM; Index++) {
    DEBUG ((EFI_D_ERROR, " %02d       0x%02X      0x%02X      %d      0x%02X     %d\n", 
                           Index, mCpuApicIdOrderTable[Index].AcpiProcessorId,
                           mCpuApicIdOrderTable[Index].ApicId,
                           mCpuApicIdOrderTable[Index].Flags,
                           mCpuApicIdOrderTable[Index].SwProcApicId,
                           mCpuApicIdOrderTable[Index].SocketNum));
  }
  

}


// the socket ID as following order: 0, 2, 1, 3
UINT32
GetExpectSocketId (
  UINT32 SocketId
  )
{
  UINT32 ExpectedSocketId;
 
  switch(SocketId) {
    case 0: 
      ExpectedSocketId = 2;
      break;
    case 1:
      ExpectedSocketId = 3;
      break;
    case 2:
      ExpectedSocketId = 1;
      break;
    case 3:
      ExpectedSocketId = 0;
      break;
    default:
      ExpectedSocketId = 0xFFFFFFFF;
      break;
  }

  return ExpectedSocketId;

}

EFI_STATUS
AppendCpuMapTableEntry (
    IN VOID   *ApicPtr,
    IN UINT32 LocalApicCounter
  )
{
  EFI_STATUS    Status;
  EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApicPtr;
  EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *LocalX2ApicPtr;
  UINT8         Type;

  Status = EFI_SUCCESS;
  Type = ((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiApicCommon.Type;
  LocalApicPtr = (EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalApic);
  LocalX2ApicPtr = (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)(&((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalx2Apic);
	
  if(Type == EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC) {
    if(!mX2ApicEnabled) {
      LocalApicPtr->Flags           = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
      LocalApicPtr->ApicId          = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].ApicId;
      LocalApicPtr->AcpiProcessorId = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
    } else {
      LocalApicPtr->Flags           = 0;
      LocalApicPtr->ApicId          = 0xFF;
      LocalApicPtr->AcpiProcessorId = (UINT8)0xFF;
      Status = EFI_UNSUPPORTED;
    }
  } else if(Type == EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC) {
    if(mX2ApicEnabled) {
      LocalX2ApicPtr->Flags            = (UINT8)mCpuApicIdOrderTable[LocalApicCounter].Flags;
      LocalX2ApicPtr->X2ApicId         = mCpuApicIdOrderTable[LocalApicCounter].ApicId;
      LocalX2ApicPtr->AcpiProcessorUid = mCpuApicIdOrderTable[LocalApicCounter].AcpiProcessorId;
    } else {
      LocalX2ApicPtr->Flags            = 0;
      LocalX2ApicPtr->X2ApicId         = (UINT32)-1;
      LocalX2ApicPtr->AcpiProcessorUid = (UINT32)-1;
      Status = EFI_UNSUPPORTED;
    }
  } else {
    Status = EFI_UNSUPPORTED;
  }

  return Status;

}

EFI_STATUS
SortCpuLocalApicInTable (
  IN  EFI_MP_SERVICES_PROTOCOL  *MpService,
  IN  UINTN                     NumberOfCPUs
  )
{
  EFI_STATUS                                Status;
  EFI_PROCESSOR_INFORMATION                 ProcessorInfoBuffer;
  UINTN                                     BufferSize;
  UINT32                                    Index;
  UINT32                                    CurrProcessor;
  UINT32                                    BspApicId;
  UINT32                                    TempVal = 0;
  UINT32                                    TempVal2;
  EFI_CPU_ID_ORDER_MAP                      *CpuIdMapPtr;
  UINT32                                    CoreThreadMask;
//  UINT32                                    tempCoreNum, currentCore, currentSkt;

  BufferSize = 0;
  Index      = 0;
  Status     = EFI_SUCCESS;

  CoreThreadMask = (UINT32) ((1 << mNumOfBitShift) - 1);

  if(!mCpuOrderSorted) {

  //Init mCpuIndexTable 
    for (CurrProcessor = 0; CurrProcessor < (MAX_THREAD * MAX_CORE); CurrProcessor++) {
        mCpuIndexTable[CurrProcessor] = (UINT32) -1;
    }

  //Init ProcessorBitMask table
    for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {
        mAcpiParameter->ProcessorBitMask[Index] = 0;
    }

  //Counter number of cores
  for (Index = 0; Index < 32; Index++) {
    if ((mPlatformInfo->CpuData.SkuSlices >> Index) & 0x1) {
      TempVal++;
    }
  }

  DEBUG ((EFI_D_ERROR, "::ACPI::  Enabled threads in CPU (count from CAPID5) = %x\n", TempVal));


   Index  = 0;

   // currentSkt = 0;
   // tempCoreNum = 0;
   // currentCore = 0;
    for (CurrProcessor = 0; CurrProcessor < NumberOfCPUs; CurrProcessor++) {
      Status = MpService->GetProcessorInfo (
                                            MpService,
                                            CurrProcessor,
                                            &ProcessorInfoBuffer
                                            );

      if ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0) {
        if(ProcessorInfoBuffer.ProcessorId & 1) { //is 2nd thread
          CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[(Index - 1) + MAX_CPU_NUM / 2];
        } else { //is primary thread       
          CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[Index];
          Index++;
        }
   /**     if(ProcessorInfoBuffer.Location.Package != currentSkt) {
          currentSkt = ProcessorInfoBuffer.Location.Package;
          tempCoreNum = 0;      //reset current core number BUGBUG: as the CORE code order thread per ApicId, so we can use this
        }
        if(currentCore != ProcessorInfoBuffer.Location.Core) {
          tempCoreNum++;
          currentCore = ProcessorInfoBuffer.Location.Core;
        }**/
   //  DEBUG ((EFI_D_ERROR, "proc[%02x] ApicId %08X Pkg %02X, CORE: %02X, T: %x: tempCore: %02X\n", CurrProcessor,(UINT32)ProcessorInfoBuffer.ProcessorId,ProcessorInfoBuffer.Location.Package,ProcessorInfoBuffer.Location.Core,ProcessorInfoBuffer.Location.Thread,tempCoreNum));
        CpuIdMapPtr->ApicId  = (UINT32)ProcessorInfoBuffer.ProcessorId;
        CpuIdMapPtr->Flags   = ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0);
        /**CpuIdMapPtr->AcpiProcessorId = ((UINT32)ProcessorInfoBuffer.Location.Package * MAX_CORE * 2) + \
                                        + (tempCoreNum * 2) + (ProcessorInfoBuffer.Location.Thread);**/
        CpuIdMapPtr->AcpiProcessorId = CpuIdMapPtr->ApicId;
                                        
        CpuIdMapPtr->SwProcApicId = ((UINT32)(ProcessorInfoBuffer.Location.Package << mNumOfBitShift) + (((UINT32)ProcessorInfoBuffer.ProcessorId) & CoreThreadMask));
        CpuIdMapPtr->SocketNum = (UINT32)ProcessorInfoBuffer.Location.Package;
        if(mX2ApicEnabled) { //if X2Apic, re-order the socket # so it starts from base 0 and contiguous
          //may not necessory!!!!!
        }

        //update processorbitMask   3f0ff  --> 00ff03ff
        //mAcpiParameter->ProcessorBitMask[CpuIdMapPtr->SocketNum] |= LShiftU64(1, ((ProcessorInfoBuffer.Location.Core * 2) + ProcessorInfoBuffer.Location.Thread));
        if (CpuIdMapPtr->Flags == 1) {
          mAcpiParameter->ProcessorBitMask[CpuIdMapPtr->SocketNum] |= LShiftU64(1, (ProcessorInfoBuffer.ProcessorId & CoreThreadMask) );
        }

      } else { //not enabled
        CpuIdMapPtr = (EFI_CPU_ID_ORDER_MAP *)&mCpuApicIdOrderTable[Index];
        CpuIdMapPtr->ApicId  = (UINT32)-1;
        CpuIdMapPtr->Flags   = 0;
        CpuIdMapPtr->AcpiProcessorId = (UINT32)-1;
        CpuIdMapPtr->SwProcApicId = (UINT32)-1;
        CpuIdMapPtr->SocketNum = (UINT32)-1;

      }
      
    }
    //keep for debug purpose
    DEBUG(( EFI_D_ERROR, "::ACPI::  APIC ID Order Table Init.   CoreThreadMask = %x,  mNumOfBitShift = %x\n", CoreThreadMask, mNumOfBitShift));
    DEBUG(( EFI_D_ERROR, "::ACPI::                              GT16 = %x\n",  mAcpiParameter->CpuSkuNumOfBitShift));
    DebugDisplayReOrderTable();
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorBitMask[0]: %x %x\n", (mAcpiParameter->ProcessorBitMask[0] >> 32), mAcpiParameter->ProcessorBitMask[0]));
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorBitMask[1]: %x %x\n", (mAcpiParameter->ProcessorBitMask[1] >> 32), mAcpiParameter->ProcessorBitMask[1]));
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorBitMask[2]: %x %x\n", (mAcpiParameter->ProcessorBitMask[2] >> 32), mAcpiParameter->ProcessorBitMask[2]));
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorBitMask[3]: %x %x\n", (mAcpiParameter->ProcessorBitMask[3] >> 32), mAcpiParameter->ProcessorBitMask[3]));
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorApicIdBase[0]: %x\n", mAcpiParameter->ProcessorApicIdBase[0]));
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorApicIdBase[1]: %x\n", mAcpiParameter->ProcessorApicIdBase[1]));
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorApicIdBase[2]: %x\n", mAcpiParameter->ProcessorApicIdBase[2]));
    DEBUG ((EFI_D_ERROR, "::ACPI::  ProcessorApicIdBase[3]: %x\n", mAcpiParameter->ProcessorApicIdBase[3]));

    //make sure 1st entry is BSP
    if(mX2ApicEnabled) {
      BspApicId = (UINT32)AsmReadMsr64(0x802);
    } else {
      BspApicId = (*(volatile UINT32 *)(UINTN)0xFEE00020) >> 24;
    }

    if(mCpuApicIdOrderTable[0].ApicId != BspApicId) {
      //check to see if 1st entry is BSP, if not swap it
      Index = ApicId2SwProcApicId(BspApicId);

    if(MAX_CPU_NUM <= Index) {
	      DEBUG ((EFI_D_ERROR, "Asserting the SortCpuLocalApicInTable Index Bufferflow\n"));
      ASSERT_EFI_ERROR(EFI_INVALID_PARAMETER);
    }
      TempVal = mCpuApicIdOrderTable[Index].ApicId;
      mCpuApicIdOrderTable[Index].ApicId = mCpuApicIdOrderTable[0].ApicId;
      mCpuApicIdOrderTable[0].ApicId = TempVal;
      mCpuApicIdOrderTable[Index].Flags = mCpuApicIdOrderTable[0].Flags;
      mCpuApicIdOrderTable[0].Flags = 1;
      TempVal = mCpuApicIdOrderTable[Index].SwProcApicId;
      mCpuApicIdOrderTable[Index].SwProcApicId = mCpuApicIdOrderTable[0].SwProcApicId;
      mCpuApicIdOrderTable[0].SwProcApicId = TempVal;
      //swap AcpiProcId
      TempVal = mCpuApicIdOrderTable[Index].AcpiProcessorId;
      mCpuApicIdOrderTable[Index].AcpiProcessorId = mCpuApicIdOrderTable[0].AcpiProcessorId;
      mCpuApicIdOrderTable[0].AcpiProcessorId = TempVal;
      
    }
		
    //Make sure no holes between enabled threads
    for(CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
  
      if(mCpuApicIdOrderTable[CurrProcessor].Flags == 0) {
        //make sure disabled entry has ProcId set to FFs
        mCpuApicIdOrderTable[CurrProcessor].ApicId = (UINT32)-1;
        mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = (UINT32)-1;
        mCpuApicIdOrderTable[CurrProcessor].SwProcApicId = (UINT32)-1;
        
        for(Index = CurrProcessor+1; Index < MAX_CPU_NUM; Index++) {
          if(mCpuApicIdOrderTable[Index].Flags == 1) {
            //move enabled entry up
            mCpuApicIdOrderTable[CurrProcessor].Flags = 1;
            mCpuApicIdOrderTable[CurrProcessor].ApicId = mCpuApicIdOrderTable[Index].ApicId;
            mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = mCpuApicIdOrderTable[Index].AcpiProcessorId;
            mCpuApicIdOrderTable[CurrProcessor].SwProcApicId = mCpuApicIdOrderTable[Index].SwProcApicId;
            mCpuApicIdOrderTable[CurrProcessor].SocketNum = mCpuApicIdOrderTable[Index].SocketNum;
            //disable moved entry
            mCpuApicIdOrderTable[Index].Flags = 0;
            mCpuApicIdOrderTable[Index].ApicId = (UINT32)-1;
            mCpuApicIdOrderTable[Index].AcpiProcessorId = (UINT32)-1;
            mCpuApicIdOrderTable[Index].SwProcApicId = (UINT32)-1;
            break;
          }
        }
      }
    }

    //keep for debug purpose
    DEBUG ((EFI_D_ERROR, "APIC ID Order Table ReOrdered\n"));
    DebugDisplayReOrderTable();

    //
    // Update mCpuIndexTable with all possible current APIC IDs in order
    //
    for(Index = 0; Index < MAX_CPU_NUM ; Index++) { 
      if((mCpuApicIdOrderTable[Index].Flags == 1)) {
        //
        // Go through current mCpuIndexTable table and add APIC ID if it is not there
        //
        for(CurrProcessor = 0; CurrProcessor < (MAX_THREAD*MAX_CORE); CurrProcessor++) {
          if (mCpuIndexTable[CurrProcessor] == (mCpuApicIdOrderTable[Index].ApicId & CoreThreadMask)) {
            //
            // Current entry already added, go to next
            //
            break;
          }
          //
          // Sort the new APIC ID into the current array, even first, low to high, then odd
          //
          if ((mCpuApicIdOrderTable[Index].ApicId & CoreThreadMask) % 2 == 0) {
            //
            // If inserting APIC ID is less than current, current is odd number, or we have reached the end, insert
            //
            if ((mCpuIndexTable[CurrProcessor] > (mCpuApicIdOrderTable[Index].ApicId & CoreThreadMask)) || 
                        (mCpuIndexTable[CurrProcessor] % 2 != 0) || (mCpuIndexTable[CurrProcessor] == (UINT32) -1)) {
              TempVal = mCpuIndexTable[CurrProcessor];
              mCpuIndexTable[CurrProcessor] = mCpuApicIdOrderTable[Index].ApicId & CoreThreadMask;
              //
              // Move rest of the entries back
              //
              for ( CurrProcessor = CurrProcessor+1; CurrProcessor < (MAX_THREAD*MAX_CORE); CurrProcessor++) {
                if (TempVal == (UINT32) -1)
                  break;
                TempVal2 = mCpuIndexTable[CurrProcessor];
                mCpuIndexTable[CurrProcessor] = TempVal;
                TempVal = TempVal2;
              }
              break;
            }
          } else {  // Inserting odd APIC ID
            if(mCpuIndexTable[CurrProcessor] % 2 == 0)
              continue;  // Skip all even entries in the array

            //
            // If inserting APIC ID is less than current or we have reached the end, insert
            //
            if ((mCpuIndexTable[CurrProcessor] > (mCpuApicIdOrderTable[Index].ApicId & CoreThreadMask)) || (mCpuIndexTable[CurrProcessor] == (UINT32) -1)) {
              TempVal = mCpuIndexTable[CurrProcessor];
              mCpuIndexTable[CurrProcessor] = mCpuApicIdOrderTable[Index].ApicId & CoreThreadMask;
              //
              // Move rest of the entries back
              //
              for ( CurrProcessor = CurrProcessor+1; CurrProcessor < (MAX_THREAD*MAX_CORE); CurrProcessor++) {
                if (TempVal == (UINT32) -1)
                  break;
                TempVal2 = mCpuIndexTable[CurrProcessor];
                mCpuIndexTable[CurrProcessor] = TempVal;
                TempVal = TempVal2;
              }
              break;
            }
          }
        }
      }
    }

    for(Index = 0; Index < (MAX_THREAD*MAX_CORE); Index++) {
       DEBUG ((EFI_D_ERROR, " mCpuIndexTable[%02d] = %02X\n", Index, (mCpuIndexTable[Index] & 0xFF)));
    }

    mCpuOrderSorted = TRUE;
  }

  return Status;
}



EFI_STATUS
ReadOcCap(OUT UINT8* Data)
{



  EFI_STATUS      Status;
  OC_MAILBOX_ITEM OcCapsMsg;
  UINT64          MsrData;
  Status = EFI_SUCCESS;



  ZeroMem(&OcCapsMsg,sizeof(OC_MAILBOX_ITEM));

  ///
  /// Convert OC capabilties message to Mailbox command format
  ///
  if(CheckMailboxReady ()!= EFI_SUCCESS)
  return EFI_TIMEOUT;

  OcCapsMsg.Data = 0;
  OcCapsMsg.Interface.Fields.Param1 = 0x00;
  OcCapsMsg.Interface.Fields.Param2 = 0x00;
  OcCapsMsg.Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_OC_CAPABILITIES;
  OcCapsMsg.Interface.Fields.RunBusy = 1;
  CopyMem (&MsrData, &OcCapsMsg, sizeof(MsrData));

  ///
  /// Write mailbox command to OC mailbox
  ///
  AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);


  if(CheckMailboxReady ()!= EFI_SUCCESS)
  return EFI_TIMEOUT;

  MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
  DEBUG(( EFI_D_ERROR, "::OC CAPDATA = %x\n", MsrData));
  *Data = (UINT8)(MsrData & 0xFF);
   
return Status;

}



EFI_STATUS
CheckMailboxReady (VOID)
{
  EFI_STATUS              Status;
  UINT16                  StallCount;
  UINT8                   RunBusyBit;
  UINT64                  MsrData;
 
  OC_MAILBOX_FULL         OcMailboxFull;
  

  Status = EFI_SUCCESS;
  StallCount = 0;
  RunBusyBit = 1;

  do {
        ///
        /// Read the OC mailbox run/busy state
        ///
        MsrData = AsmReadMsr64(OC_MAILBOX_MSR);
        CopyMem(&OcMailboxFull.Data, &MsrData, sizeof(OcMailboxFull));
        RunBusyBit = OcMailboxFull.Interface.Fields.RunBusy;
      
		//
		// Wait for 1us
		//
		//PchPmTimerStall(MAILBOX_WAIT_STALL);
		StallCount++;
  }
  while ((RunBusyBit == 1) && (StallCount < MAILBOX_WAIT_TIMEOUT));

  if ((RunBusyBit == 1) && (StallCount == MAILBOX_WAIT_TIMEOUT)) {
    //DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox interface timed out.\n"));
    Status = EFI_TIMEOUT;
  }
  return Status;
}

#ifndef  GRANGEVILLE_FLAG
EFI_STATUS
EFIAPI
GetCoreControlCapability (VOID)
/**
  Get the Core control capability
  @retval EFI_STATUS
**/
{
  EFI_STATUS      Status;
  UINT32          CommandId;
  OC_MAILBOX_ITEM SvidMsg;
  UINT32          LibStatus;
  
  Status = EFI_SUCCESS;
  ZeroMem(&SvidMsg, sizeof(SvidMsg));

  ///
  /// Convert SVID message to Mailbox command format
  ///
  CommandId = OC_LIB_CMD_GET_CORE_CONTROL;
  ConvertToMailboxFormat(&SvidMsg, CommandId);

  ///
  ///  Read From the OC Library
  ///
  Status = MailboxRead(MAILBOX_TYPE_OC, OC_LIB_CMD_GET_CORE_CONTROL, &SvidMsg.Data, &LibStatus);

  ///
  ///  Copy mailbox data to SvidConfig
  ///
  if ((Status == EFI_SUCCESS) && (LibStatus == 0))
    Status = EFI_SUCCESS;
  else
    Status = EFI_NOT_FOUND;

  return Status;
}

VOID
ConvertToMailboxFormat (
  OUT OC_MAILBOX_ITEM *MailboxData,
  IN UINT32           CommandId
  )
/**
  Converts the input data to valid mailbox command format based on CommandID

@param[OUT] *MailboxData
@param[IN]  CommandId
**/
{
  ///
  ///  Initialize local varaibles and mailbox data
  ///
  ZeroMem ((UINT32 *)MailboxData, sizeof(OC_MAILBOX_ITEM));

  ///
  /// Then make a decision based on CommandId how to format
  ///
  //DEBUG((EFI_D_INFO, "\nCOMMAND ID :%x\n", CommandId));
  switch (CommandId) {
    case OC_LIB_CMD_GET_CORE_CONTROL:
      MailboxData->Data = 0;
      MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_CORE_CONTROL;
      break;

    default:
      // DEBUG ((EFI_D_ERROR, "(OC MAILBOX) Unkown Command ID\n"));
      break;
  }
}

EFI_STATUS
EFIAPI
MailboxRead (
  IN UINT32  MailboxType,
  IN UINT32  MailboxCommand,
  OUT UINT32 *MailboxDataPtr,
  OUT UINT32 *MailboxStatus
  )
/**
  Generic Mailbox function for mailbox read commands. This function will write
  the read request, and populate the read results in the output data.

  @param[IN]  MailboxType,
  @param[IN]  MailboxCommand,
  @param[OUT] *MailboxDataPtr,
  @param[OUT] *MailboxStatus

  @retval EFI_STATUS
**/
{
  EFI_STATUS         Status;
  UINT64             MsrData;
  OC_MAILBOX_FULL    OcMailboxFull;
  OC_MAILBOX_FULL    OcMailboxFullVerify;

  ///
  ///  Poll the run/busy to ensure the interface is available
  ///
  Status = PollMailboxReady(MailboxType);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  //DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Read Command = %2X\n", (UINT8)MailboxCommand));

  switch (MailboxType)
  {
    case MAILBOX_TYPE_OC:
      ///
      /// Set the Run/Busy bit to signal mailbox data is ready to process
      ///
      OcMailboxFull.Interface.InterfaceData = MailboxCommand;
      OcMailboxFull.Data = *MailboxDataPtr;
      OcMailboxFull.Interface.Fields.RunBusy = 1;
      CopyMem (&MsrData, &OcMailboxFull, sizeof(MsrData));

      ///
      /// Write mailbox command to OC mailbox
      ///
      AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);

      ///
      /// Poll run/busy to indicate the completion of write request
      ///
      PollMailboxReady(MailboxType);

      ///
      /// Read the OC mailbox to verify read completion success.
      /// Mailbox protocol requires software to read back the interface twice
      /// to ensure the read results are consistent.
      ///
      MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
      CopyMem (&OcMailboxFull, &MsrData, sizeof(OcMailboxFull));

      PchPmTimerStall(MAILBOX_READ_TIMEOUT);

      MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
      CopyMem (&OcMailboxFullVerify, &MsrData, sizeof(OcMailboxFullVerify));

      ///
      /// If the data is inconsistent, we cannot trust the results
      ///
      if (OcMailboxFull.Interface.InterfaceData != OcMailboxFullVerify.Interface.InterfaceData) {
        if (OcMailboxFull.Data != OcMailboxFullVerify.Data) {
          //DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
          return EFI_INVALID_PARAMETER;
        }
      }

      ///
      ///  Copy Overclocking mailbox completion code and read results
      ///
      *MailboxStatus = OcMailboxFull.Interface.Fields.CommandCompletion;
      CopyMem(MailboxDataPtr, &OcMailboxFull.Data, sizeof(UINT32));
      break;

    default:
      //DEBUG ((EFI_D_ERROR, "(MAILBOX) Unrecognized Mailbox Type.\n"));
      Status = EFI_UNSUPPORTED;
      break;
  }

  //DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Status = %2X\n", *MailboxStatus));

  return Status;
}

/**
  Poll the run/busy bit of the mailbox until available or timeout expires.

  @param[IN]  MailboxType,

  @retval EFI_STATUS
**/
EFI_STATUS
EFIAPI
PollMailboxReady (
  IN UINT32 MailboxType
  )
{
  EFI_STATUS              Status;
  UINT16                  StallCount;
  UINT8                   RunBusyBit;
  UINT64                  MsrData;
  OC_MAILBOX_FULL         OcMailboxFull;

  Status = EFI_SUCCESS;
  StallCount = 0;
  RunBusyBit = 1;

  do {
    switch (MailboxType)
    {
      case MAILBOX_TYPE_OC:
        ///
        /// Read the OC mailbox run/busy state
        ///
        MsrData = AsmReadMsr64(OC_MAILBOX_MSR);
        CopyMem(&OcMailboxFull.Data, &MsrData, sizeof(OcMailboxFull));
        RunBusyBit = OcMailboxFull.Interface.Fields.RunBusy;
        break;
    }
    //
    // Wait for 1us
    //
    PchPmTimerStall(MAILBOX_WAIT_STALL);
    StallCount++;
  }
  while ((RunBusyBit == 1) && (StallCount < MAILBOX_WAIT_TIMEOUT));

  if ((RunBusyBit == 1) && (StallCount == MAILBOX_WAIT_TIMEOUT)) {
    //DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox interface timed out.\n"));
    Status = EFI_TIMEOUT;
  }
  return Status;
}
#endif

